uni-app中怎么开发一个全局弹层组件(代码示例)

uni-app中怎么开发一个全局弹层组件?下面本篇文章给大家通过例子介绍一下uni-app中实现一个全局弹层组件的方法,希望对大家有所帮助! 公司有一个采用uni-app框架写的a...

uni-app中怎么开发一个全局弹层组件?下面本篇文章给大家通过例子介绍一下uni-app中实现一个全局弹层组件的方法,希望对大家有所帮助!

uni-app中怎么开发一个全局弹层组件(代码示例)插图1

公司有一个采用uni-app框架写的app应用,里面的弹层基本是使用官方的uni.showModal之类的api实现弹层,在设备上表现就是原生的弹层,在客户的要求下,需要更换成设计的样式,所以就开始实现这样一个组件。

根据弹层经常使用的方法和方式可以大致列出他需要的属性和方法:

类型:alert/confirm等

展示图标 icon

展示内容 content

可以api调用

支持promise,可以使用$api.xx().then

前几项就很好做,就在data中定义好字段,外层直接拿官方的轮子uni-popup,这样少写一些控制弹出的逻辑(懒的),这样大致结构就写好了

//template部分<uni-popupref="popup":maskClick="maskClick"><viewclass="st-layer":style="{width:width}"><viewclass="st-layer__content"><!--#ifndefAPP-NVUE--><textclass="st-layer__icon":class="option.iconClass||getIconClass()"v-if="option.type!=='none'&&option.showIcon"></text><!--#endif--><viewclass="st-layer__msg"v-if="option.msg"><text>{{option.msg}}</text></view></view><viewclass="st-layer__footer":class="{'is-reverse-cofirmcancel':isReverseConfirmCancel}"v-if="option.showConfirmButton||option.showCancelButton"><viewclass="st-layer__footer__btnst-layer__footer__btn--confirm"@tap.stop="confirmClick"v-if="option.showConfirmButton"><text>确认</text></view><viewclass="st-layer__footer__btnst-layer__footer__btn--cancel"@tap.stop="cancelClick"v-if="option.showCancelButton"><text>取消</text></view></view></view></uni-popup>

然后js部分先简单实现了一些open和close方法

data(){return{option:{}}},methods:{open(option){letdefaultOption={showCancelButton:false,//是否显示取消按钮cancelButtonText:'取消',//取消按钮文字showConfirmButton:true,//是否显示确认按钮confirmButtonText:'取消',//确认按钮文字showIcon:true,//是否显示图标iconClass:null,//图标class自定义type:'none',//类型confirm:null,//点击确认后的逻辑cancel:null,//点击取消后的逻辑msg:''}this.option=Object.assign({},defaultOption,option)this.$refs.popup.open()},close(){this.$refs.popup.close()},confirmClick(){constconfirmHandler=this.option.confirmif(confirmHandler&&typeofconfirmHandler==='function'){confirmHandler()}this.close()this.$emit('confirm')},cancelClick(){constcancelHandler=this.option.cancelif(cancelHandler&&typeofcancelHandler==='function'){cancelHandler()}this.close()this.$emit('cancel')}}

目前在其他页面已经可以使用

//test.vue可以使用uni-app的[easycom组件规范](https://uniapp.dcloud.io/component/README?id=easycom%e7%bb%84%e4%bb%b6%e8%a7%84%e8%8c%83),不用写import语句<st-layerref="stLayer"></st-layer>//js部分this.$refs.stLayer.open({msg:'测试',confirm:()=>{console.log('点击了确认')},cancel:()=>{console.log('点击了取消')}})

现在基本功能已经实现,但是有人要说了,这样调用不方便,我想这样调用

open(msg).then(()=>{console.log('点击了确认')}).catch(()=>{console.log('点击了取消')})

那如何实现promise化呢?最简单的方法就是让open方法返回一个promise。如何点击确认或取消的时候进入then方法呢,看下面的写法

...open(){returnnewpromise((reoslve,reject)=>{...this.option.confirm=this.option.confirm||functionconfirmResolve(){resolve()}this.option.cancel=this.option.cancel||functioncancelReject(){reject()}})}...

如果要封装其他单独的方法,比如confirm之类,可以在open基础上扩展:

confirm(msg,option={}){if(typeofmsg==='object'){option=msg}else{option.msg=msg}returnthis.open({...option,showCancelButton:true,type:'confirm'})}//调用方式this.$refs.stLayer.confirm('是否确认?').then().catch()

这样基本的弹层组件已经实现。下面也就是最后一步全局使用原有vue项目写的layer组件要全局使用通常是采用下面的方法注入到页面中

importmainfrom'./main.vue'constLayerConstructor=vue.extend(main)constinitInstance=()=>{instance=newLayerConstructor({el:document.createElement('div')})instance.callback=defaultCallbackdocument.getElementById('app').appendChild(instance.$el)}

直接拉过来用,结果报错,提示error: document is undefined,才想起uni-app跟普通vue项目的有一个很大的区别,在它的运行原理中有介绍:

uni-app逻辑层和视图层分离,在非H5端运行时,从架构上分为逻辑层和视图层两个部分。逻辑层负责执行业务逻辑,也就是运行js代码,视图层负责页面渲染。虽然开发者在一个vue页面里写js和css,但其实,编译时就已经将它们拆分了。逻辑层是运行在一个独立的jscore里的,它不依赖于本机的webview,所以一方面它没有浏览器兼容问题,可以在Android4.4上跑es6代码,另一方面,它无法运行window、document、navigator、localstorage等浏览器专用的js API。

所以这种注册全局的方法已经不可用。那该如何在uni-app中实现呢? 翻看官方论坛,找到了一个实现loadervue-inset-loader,实现原理就是获取sfc模板内容,在指定位置插入自定义内容(也就是需要全局的组件),使用方式如下:

//第一步npminstallvue-inset-loader--save-dev//第二步在vue.config.js(hbuilderx创建的项目没有的话新建一个)中注入loadermodule.export={chainWebpack:config=>{//超级全局组件config.module.rule('vue').test(/\.vue$/).use().loader(path.resolve(__dirname,"./node_modules/vue-inset-loader")).end()}}//支持自定义pages.json文件路径//options:{//pagesPath:path.resolve(__dirname,'./src/pages.json')//}//第三步pages.json配置文件中添加insetLoader"insetLoader":{"config":{"confirm":"<BaseConfirmref='confirm'></BaseConfirm>","abc":"<BaseAbcref='BaseAbc'></BaseAbc>"},//全局配置"label":["confirm"],"rootEle":"div"}配置说明

config(default:{})

定义标签名称和内容的键值对

label(default:[])

需要全局引入的标签,打包后会在所有页面引入此标签

rootEle(default:"div")

根元素的标签类型,缺省值为div,支持正则,比如匹配任意标签 ".*"

label和rootEle支持在单独页面的style里配置,优先级高于全局配置

到这,该组件就可以全局使用了,不需要在每个页面写标签使用,只需要调用api就可以。

后面可以再根据使用情况进行优化处理。水平有限,欢迎各位大佬指点。

产品猿社区致力收录更多优质的商业产品,给服务商以及软件采购客户提供更多优质的软件产品,帮助开发者变现来实现多方共赢;

日常运营的过程中我们难免会遇到各种版权纠纷等问题,如果您在社区内发现有您的产品未经您授权而被用户提供下载或使用,您可按照我们投诉流程处理,点我投诉

本文来自用户发布投稿,不代表产品猿立场 ;若对此文有疑问或内容有严重错误,可联系平台客服反馈;

部分产品是用户投稿,可能本文没有提供官方下下载地址或教程,若您看到的内容没有下载入口,您可以在我们产品园商城搜索看开发者是否有发布商品;若您是开发者,也诚邀您入驻商城平台发布的产品,地址:点我进入

如若转载,请注明出处:https://www.chanpinyuan.cn/33453.html;
(0)
上一篇 2023年1月17日 下午4:17
下一篇 2023年1月17日 下午4:17

相关推荐

发表回复

登录后才能评论
分享本页
返回顶部