之前的文章有研究过在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插件,看了一下介绍基本满足需求,开始着手实验。
引入
先是建立了一个空项目,引入插件,一开始不太熟悉使用方式,调试了很久,步骤如下。
建立一个公共组件
我这里以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()],
};
});
注意:'pages'是一个string不是一个数组,这里和文档中介绍的方式有出入
pages.json
添加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>
效果
嵌入位置
在图中可以看到,填写了package,会包裹组件和页面。
如果不填写,只配置如下
"insetLoader": {
// config仅可在insetLoader中配置,不可在pages中配置
"config": {
"popup": "<GlobalPopup ref='GlPopupRef'></GlobalPopup>"
},
"label": ["popup"]
}
外层就没有顶级节点包裹
注意:如果出现配置完成但是查看wxml结构,没有加载全局组件,尝试关闭微信开发者助手,重新编译运行hbuilder程序