uniapp小程序全局函数组件的实现(自定义模态框)

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>

到这里就全部完成了 下一章我会写一下自定义全局提示的全局组件调用

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值