之前的文章有研究过在Taro中开发微信小程序,如何不每个页面都引入组件,以最简便的方式实现一个全局弹窗,研究过后没有发现可行的方案,最终是通过在Taro中开发一个通用组件,通用组件没有实际内容,只挂载需要引入的全局组件,然后用通用组件去包裹每个页面

// 全局组件  app-config-provider.vue
<templete>
  <view>
    <slot></slot>
        // 全局弹窗
    <common-login-popup />
   </view>
</templete>



// 某个页面

<templete>
  <app-config-provider>
    ........
  </app-config-provider>
</templete>

这种方式虽然可以实现但是很不方便,最近重新拾起研究了一下,发现一个新的实现方式。

关于之前的研究过程可以查看这篇文章


介绍

先是从网上搜集到了vue-inset-loader这个插件,了解过后发现不是太匹配,又从uniapp市场中找到了vite-inset-loader插件,看了一下介绍基本满足需求,开始着手实验。

引入

先是建立了一个空项目,引入插件,一开始不太熟悉使用方式,调试了很久,步骤如下。

建立一个公共组件

2025-02-26T03:01:37.png

我这里以GlobalPopup.vue为例

<template>
    <view type="center" v-if="isopen">
        <view class="custom-popup">
            <text class="title">{{ title }}</text>
            <slot name="content"></slot>
            <button @click="close">关闭</button>
        </view>
    </view>
</template>

<script setup>
    import {
        ref
    } from 'vue';

    const props = defineProps({
        title: {
            type: String,
            default: '提示'
        }
    });
    const isopen = ref(false)

    const popupRef = ref(null);

    const open = () => {
        console.log('打开全局弹窗')        
        isopen.value = true
    };
    const close = () => isopen.value = false;

    defineExpose({
        open,
        close
    });
</script>

<style scoped>
    .custom-popup {
        background: #fff;
        padding: 40rpx;
        border-radius: 16rpx;
    }

    .title {
        font-size: 32rpx;
        margin-bottom: 24rpx;
    }
</style>

vite.config.js

调整vite配置文件

import { defineConfig } from 'vite';
import uni from '@dcloudio/vite-plugin-uni';
import viteInsetLoader from 'vite-inset-loader';

export default defineConfig(() => {
  return {
    plugins: [viteInsetLoader({include:'pages'}), uni()],
  };
});

2025-02-26T03:02:34.png

注意:'pages'是一个string不是一个数组,这里和文档中介绍的方式有出入

pages.json

2025-02-26T03:05:35.png

添加insetLoader选项

    "insetLoader": {
        // config仅可在insetLoader中配置,不可在pages中配置
        "config": {
            "popup": "<GlobalPopup ref='GlPopupRef'></GlobalPopup>"
        },
        "label": ["popup"],
        "package": {
            "label": "div",
            "options": {
                "id": "demo-id",
                "class": "dev-style",
                "style": {
                    "font-size": "24px"
                }
            }
        }
    }

到此引入完成,下面开始使用

使用

在insetLoader配置中设置了ref,在页面可以直接引用

<template>
    <view class="content">
        <image class="logo" src="/static/logo.png"></image>
        <view class="text-area">
            <button @click="openPopup">打开全局弹窗</button>
            <navigator url="/pages/popup/popup">
                <button>另一个页面</button>
            </navigator>
        </view>
    </view>
</template>

<script setup>
    import {
        onMounted,
        ref
    } from 'vue';

    const title = ref('Hello')
    const GlPopupRef = ref(null)

    onMounted(() => {})

    const openPopup = () => {
        console.log(GlPopupRef.value)
        GlPopupRef.value.open()
    }
</script>

<style>
    .content {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }

    .logo {
        height: 200rpx;
        width: 200rpx;
        margin-top: 200rpx;
        margin-left: auto;
        margin-right: auto;
        margin-bottom: 50rpx;
    }

    .text-area {
        display: flex;
        justify-content: center;
    }

    .title {
        font-size: 36rpx;
        color: #8f8f94;
    }
</style>

效果

效果图

嵌入位置

2025-02-26T05:09:10.png

在图中可以看到,填写了package,会包裹组件和页面。
如果不填写,只配置如下

    "insetLoader": {
        // config仅可在insetLoader中配置,不可在pages中配置
        "config": {
            "popup": "<GlobalPopup ref='GlPopupRef'></GlobalPopup>"
        },
        "label": ["popup"]
    }

外层就没有顶级节点包裹

2025-02-26T05:12:45.png

注意:如果出现配置完成但是查看wxml结构,没有加载全局组件,尝试关闭微信开发者助手,重新编译运行hbuilder程序

最后修改:2025 年 02 月 26 日
如果觉得我的文章对你有用,奖励一杯咖啡吧!