h5实现全局函数组件
由于我最开始使用uniapp只是用来编译h5 由于可以使用document来添加删除节点 所以很容易可以实现全局函数组件,详细代码如下
// #ifdef H5
import confirm from '@/components/common/SaasConfirm.vue'
const confirmClass = Vue.extend(confirm);
let newConfirmClass = null;
const initConfirm = () => {
newConfirmClass = new confirmClass()
document.body.appendChild(newConfirmClass.$mount().$el)
}
const mpConfirm = function (options){
if (!newConfirmClass) {
initConfirm();
}
Object.assign(newConfirmClass, options);
return newConfirmClass.show(vm => {
newConfirmClass = null; // 调用之后即清空
})
}
// #endif
模态框的组件如下
<template>
<view class="saas-confirm flex-center" v-show="computedVisible">
<view class="saas-confirm-content fc">
<view class="saas-confirm-content-top">
<view class="saas-confirm-content-top-header" v-if="this.title">{{ title }}</view>
<view class="saas-confirm-content-top-center" v-html="content"></view>
</view>
<view class="fr saas-confirm-content-footer">
<view @click = 'cancel' class="saas-confirm-content-footer-button flex-center" v-if="!noCancel">{{cancelText}}</view>
<view @click = 'confirm' :class="['saas-confirm-content-footer-button flex-center saas-confirm-content-footer-active',seconds?'saas-confirm-content-footer-disable':'']">{{ seconds ? computedContent : confirmText }}</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "SaasConfirm",
data(){
return{
title: '',
content:'确认删除吗?',
cancelText : '取消',
confirmText : '确定',
seconds:0,
changeText:'确认(X)',
endText:'确认',
time:null,
noCancel:false,
visible: false
}
},
computed:{
computedContent(){
if (this.seconds){
return this.changeText.replace('X',String(this.seconds))
}else {
return this.endText
}
},
computedVisible(){
// #ifdef H5
return true
// #endif
}
},
methods:{
show(func) {
this.start()
typeof func === "function" && func.call(this, this);
return new Promise((resolve, reject) => {
this.reject = reject;
this.resolve = resolve;
});
},
cancel() {
this.reject("cancel");
this.hide();
},
confirm() {
if (this.seconds){
return true
}
this.resolve("confirm");
this.hide();
},
hide() {
// #ifdef H5
document.body.removeChild(this.$el);
this.time = null
this.$destroy();
// #endif
},
start(){
if (this.time){
return true
}
this.time = setInterval(()=>{
if (this.seconds){
this.seconds--
}else {
this.time = null
}
},1000)
}
}
}
</script>
微信小程序实现全局函数组件
但是由于小i程序没有doucument就无法通过该方法实现
想要在小程序中实现我们首先要考虑怎么在每个页面都加上该组件,很显然通过手动加入是很不理想的一个状态
这里可以使用第三方库vue-inset-loader
npm i vue-inset-loader
在这里我安装过以后出现了以下报错
这个原因是因为vue跟vue-template-compiler版本不一样引起的报错
但是我的package.json的两个版本是一样的
我重新执行 npm i也不行
后来我将vue-template-compiler卸载 重新安装了与vue一样的版本就解决了
npm uninstall vue-template-compiler
npm i vue-template-compiler@指定版本
安装好以后我们要在vue.config.js(没有手动创建一个,在根目录下)
// #ifdef MP-WEIXIN
const path = require('path')
// #endif
module.exports = {
// #ifdef MP-WEIXIN
module: {
rules: [{
test: /\.vue$/,
use: {
loader: path.resolve(__dirname, "./node_modules/vue-inset-loader")
},
}]
},
// #endif
},
};
接着在page.json中配置要全局添加的组件
"insetLoader": {
"config": {
"SaasConfirm": "<SaasConfirm ref='SaasConfirm' id='saasConfirm'/>"
},
"label": ["SaasConfirm"],
"rootEle": ".*"
},
"easycom": {
"autoscan": true,
"custom": {
"SaasConfirm": "@/components/common/SaasConfirm.vue"
}
}
然后重新编译就会发现每个页面已经引入了SaasConfirm这个组件
接下来就是怎么把组件函数化控制他的显隐
这里我们要用到uniapp的一个api getCurrentPages
这个api可以获取到当前页面的实例
// #ifdef MP-WEIXIN
const mpConfirm = function (options){
const page = getCurrentPages()[0].$vm
const newConfirmClass = page.$refs.SaasConfirm
Object.assign(newConfirmClass, options);
return newConfirmClass.show()
}
// #endif
Vue.prototype.$confirm = mpConfirm
到这一步我们就将组件函数化了
调用如方法如下
this.$confirm({content:`确认删除${this.task.name}任务吗?任务一旦删除就无法恢复!`,seconds:5})
.then(async ()=>{
try {
this.$message.success('删除成功')
} catch(e) {
console.error(e)
}
})
.catch(()=>{})
另外需要在自定义组件中处理下兼容问题代码如下
<template>
<view class="saas-confirm flex-center" v-show="computedVisible">
<view class="saas-confirm-content fc">
<view class="saas-confirm-content-top">
<view class="saas-confirm-content-top-header" v-if="this.title">{{ title }}</view>
<view class="saas-confirm-content-top-center" v-html="content"></view>
</view>
<view class="fr saas-confirm-content-footer">
<view @click = 'cancel' class="saas-confirm-content-footer-button flex-center" v-if="!noCancel">{{cancelText}}</view>
<view @click = 'confirm' :class="['saas-confirm-content-footer-button flex-center saas-confirm-content-footer-active',seconds?'saas-confirm-content-footer-disable':'']">{{ seconds ? computedContent : confirmText }}</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "SaasConfirm",
data(){
return{
title: '',
content:'确认删除吗?',
cancelText : '取消',
confirmText : '确定',
seconds:0,
changeText:'确认(X)',
endText:'确认',
time:null,
noCancel:false,
visible: false
}
},
computed:{
computedContent(){
if (this.seconds){
return this.changeText.replace('X',String(this.seconds))
}else {
return this.endText
}
},
computedVisible(){
// #ifdef H5
return true
// #endif
// #ifdef MP-WEIXIN
return this.visible
// #endif
}
},
methods:{
show(func) {
// #ifdef MP-WEIXIN
this.visible = true
// #endif
this.start()
typeof func === "function" && func.call(this, this);
return new Promise((resolve, reject) => {
this.reject = reject;
this.resolve = resolve;
});
},
cancel() {
this.reject("cancel");
this.hide();
},
confirm() {
if (this.seconds){
return true
}
this.resolve("confirm");
this.hide();
},
hide() {
// #ifdef H5
document.body.removeChild(this.$el);
this.time = null
this.$destroy();
// #endif
// #ifdef MP-WEIXIN
this.visible = false
this.time = null
// #endif
},
start(){
if (this.time){
return true
}
this.time = setInterval(()=>{
if (this.seconds){
this.seconds--
}else {
this.time = null
}
},1000)
}
}
}
</script>
到这里就全部完成了 下一章我会写一下自定义全局提示的全局组件调用