【uniapp-小步调】实现方法调用的全局tips弹窗

打印 上一主题 下一主题

主题 982|帖子 982|积分 2956

笑死,只有在想找工作的时间才会想更新博客。
开发背景

本来是个uniapp开发的H5项目,但是由于上面要求需要转为小步调版本,导致很多原先支持的功能都需要针对小步调环境举行兼容。这次先说说自定义的全局提示弹窗。代码中使用了较多uniapp组件,详细使用方法请查看uniapp官方文档
框架:uniapp、小步调、vue2
弹窗组件

弹窗组件其实就是个常规的vue页面,通过设置蒙层+层级实现弹窗结果,实现简单,可扩展性强。


  • 样式中使用了import语法是为了覆盖uniapp原生样式,如不需要可去除;
  • safeAreaTop为自定义字段,为获取的小步调顶部状态栏高度;
  • 弹窗内容显示使用了uniapp的rich-text组件,如对弹窗内容显示要求没那么高的可以直接展示文本,如:<text decode>{{content}}</text>,其中decode是为了实现换行;
  • 很多设置项是为了满意我项目标需求,并非必须,可按需调整。
  1. <template>
  2.         <view class="confirm-modal" v-if="visible" :style="{top:`${safeAreaTop}px`}">
  3.                 <view class="confirm-modal-mask flex justify-center align-center">
  4.                         <view class="confirm-modal-content" :style="contentStyle">
  5.                                 <view class="close-top-btn flex justify-end align-center" v-if="closeEnabled">
  6.                                         <uni-icons type="closeempty" size=20 color="#999" @click="handleClose"></uni-icons>
  7.                                 </view>
  8.                                 <view class="title flex justify-center align-center" v-if="title">
  9.                                         {{title}}
  10.                                 </view>
  11.                                 <view :style="{marginTop: closeEnabled&&!title?'24px':0}"
  12.                         class="flex justify-center align-center text-center">
  13.                                         <rich-text :nodes="content"></rich-text>
  14.                                 </view>
  15.                                 <view class="flex justify-between align-center operation">
  16.                                         <button type="primary" :plain="cancelClassName.indexOf('cancel')>-1" v-if="showCancel" @click="handleClose" class="round" :class="cancelClassName">
  17.                                                 {{cancelText}}
  18.                                         </button>
  19.                                         <button type="primary" :plain="confirmClassName.indexOf('cancel')>-1" v-if="showConfirm" @click="handleOk" class="round" :class="confirmClassName">
  20.                                                 {{confirmText}}
  21.                                         </button>
  22.                                 </view>
  23.                         </view>
  24.                 </view>
  25.         </view>
  26. </template>
  27. <script>
  28.         import {
  29.                 mapGetters
  30.         } from 'vuex'
  31.         export default {
  32.                 data() {
  33.                         return {
  34.                                 safeAreaTop: this.$safeAreaTop, // 获取小程序顶部状态栏高度,按需使用
  35.                         }
  36.                 },
  37.                 computed: {
  38.                         ...mapGetters(['confirmModal']),
  39.                         title() {
  40.                                 return this.confirmModal.title
  41.                         },
  42.                         content() {
  43.                                 return this.confirmModal.content
  44.                         },
  45.                         // 默认:default, 整行: block
  46.                         btnType() {
  47.                                 return this.confirmModal.btnType || 'default'
  48.                         },
  49.                         cancelText() {
  50.                                 return this.confirmModal.cancelText || '取消'
  51.                         },
  52.                         confirmText() {
  53.                                 return this.confirmModal.confirmText || '确定'
  54.                         },
  55.                         cancelClass() {
  56.                                 return this.confirmModal.cancelClass
  57.                         },
  58.                         confirmClass() {
  59.                                 return this.confirmModal.confirmClass
  60.                         },
  61.                         showCancel() {
  62.                                 return typeof this.confirmModal.showCancel === 'boolean' ? this.confirmModal.showCancel : true
  63.                         },
  64.                         showConfirm() {
  65.                                 return typeof this.confirmModal.showConfirm === 'boolean' ? this.confirmModal.showConfirm : true
  66.                         },
  67.                         visible() {
  68.                                 return typeof this.confirmModal.visible === 'boolean' ? this.confirmModal.visible : false
  69.                         },
  70.                         success() {
  71.                                 return this.confirmModal.success
  72.                         },
  73.                         cancel() {
  74.                                 return this.confirmModal.cancel
  75.                         },
  76.                         closeEnabled() {
  77.                                 return typeof this.confirmModal.closeEnabled === 'boolean' ? this.confirmModal.closeEnabled : false
  78.                         },
  79.                         contentStyle() {
  80.                                 return this.confirmModal.contentStyle
  81.                         },
  82.                         cancelClassName() {
  83.                                 if (this.cancelClass !== '') {
  84.                                         return this.cancelClass
  85.                                 }
  86.                                 if (this.btnType === 'block') {
  87.                                         return 'cancel-btn-block'
  88.                                 }
  89.                                 return 'cancel-btn'
  90.                         },
  91.                         confirmClassName() {
  92.                                 if (this.confirmClass !== '') {
  93.                                         return this.confirmClass
  94.                                 }
  95.                                 if (this.btnType === 'block') {
  96.                                         return 'confirm-btn-block'
  97.                                 }
  98.                                 return 'confirm-btn'
  99.                         }
  100.                 },
  101.                 beforeDestroy() {
  102.                         if (this.visible) {
  103.                                 this.$store.commit('SET_CONFIG', {
  104.                                         visible: false
  105.                                 })
  106.                         }
  107.                 },
  108.                 methods: {
  109.                         handleClose() {
  110.                                 if (typeof this.cancel === 'function') {
  111.                                         this.cancel()
  112.                                 }
  113.                                 this.$store.commit('SET_CONFIG', {
  114.                                         visible: false
  115.                                 })
  116.                         },
  117.                         handleOk() {
  118.                                 if (typeof this.success === 'function') {
  119.                                         this.success()
  120.                                 }
  121.                                 this.$store.commit('SET_CONFIG', {
  122.                                         visible: false
  123.                                 })
  124.                         }
  125.                 }
  126.         }
  127. </script>
  128. <style lang="scss" scoped>
  129.         .confirm-modal {
  130.                 height: 100%;
  131.                 width: 100%;
  132.                 overflow: hidden;
  133.                 z-index: 12;
  134.                 position: absolute;
  135.                 top: 0;
  136.                 left: 0;
  137.                 .confirm-modal-mask {
  138.                         background-color: rgba(0, 0, 0, 0.6);
  139.                         width: 100%;
  140.                         height: 100%;
  141.                         .confirm-modal-content {
  142.                                 background-color: #fff;
  143.                                 border-radius: 6px;
  144.                                 width: 85%;
  145.                                 padding: 24px;
  146.                                 position: relative;
  147.                                 .title {
  148.                                         font-weight: bold;
  149.                                         margin: 8px 0 12px 0;
  150.                                         font-size: 32rpx;
  151.                                 }
  152.                                 .close-top-btn {
  153.                                         position: absolute;
  154.                                         right: 12px;
  155.                                         top: 12px;
  156.                                 }
  157.                                 .operation {
  158.                                         width: 100%;
  159.                                         background-color: #fff;
  160.                                         flex-wrap: wrap;
  161.                                         .round {
  162.                                                 margin-top: 24px;
  163.                                         }
  164.                                         .cancel-btn{
  165.                                                 border-color:#00AEB8 !important;
  166.                                         color:#00AEB8  !important;
  167.                                                 width: 45%;
  168.                                                 font-size: 30rpx;
  169.                                                 white-space: nowrap;
  170.                                          }
  171.                                          .confirm-btn{
  172.                                                 background-color: #00AEB8  !important;
  173.                                                 width: 45%;
  174.                                                 font-size: 30rpx;
  175.                                             white-space: nowrap;
  176.                                          }
  177.                                          .cancel-btn-block{
  178.                                                 border-color:#00AEB8 !important;
  179.                                             color:#00AEB8  !important;
  180.                                                 width: 100%;
  181.                                                 font-size: 30rpx;
  182.                                             white-space: nowrap;
  183.                                          }
  184.                                          .confirm-btn-block{
  185.                                                   background-color: #00AEB8  !important;
  186.                                                 width: 100%;
  187.                                             font-size: 30rpx;
  188.                                                 white-space: nowrap;
  189.                                          }
  190.                                 }
  191.                         }
  192.                 }
  193.         }
  194. </style>
复制代码
弹窗结果如下所示:

全局调用

当我们写好弹窗组件时,就可以在需要的页面内引入调用(以上代码中各设置项的输入需更改为props传入,或通过ref绑定组件,调用组件内方法传入)。但是每次使用都得引入、调用,过于繁琐。为了方便使用,可以封装为全局引入,并在需要的页面内通过方法调用,实现方案如下:
封装设置项入参

在store内定义一个modules用来存储弹窗设置项并在getters内声明(按需):
  1. const confirmModal = {
  2.         state: {
  3.                 config: {
  4.                         title: '',
  5.                         content: '',
  6.                         btnType: 'default',
  7.                         cancelText: '取消',
  8.                         confirmText: '确定',
  9.                         cancelClass: '',
  10.                         confirmClass: '',
  11.                         showCancel: true,
  12.                         showConfirm: true,
  13.                         visible: false,
  14.                         success: null,
  15.                         cancel: null,
  16.                         closeEnabled: false,
  17.                         contentStyle: '',
  18.                 }
  19.         },
  20.         mutations: {
  21.                 SET_CONFIG: (state, config) => {
  22.                         const defaultConfig = {
  23.                                 content: '',
  24.                                 btnType: 'default',
  25.                                 cancelText: '取消',
  26.                                 confirmText: '确定',
  27.                                 cancelClass: '',
  28.                                 confirmClass: '',
  29.                                 showCancel: true,
  30.                                 showConfirm: true,
  31.                                 visible: true,
  32.                                 success: null,
  33.                                 cancel: null,
  34.                                 title: '',
  35.                                 closeEnabled: false,
  36.                                 contentStyle: ''
  37.                         }
  38.                         if (typeof config === 'string') {
  39.                                 state.config = Object.assign(defaultConfig, {
  40.                                         content: options
  41.                                 });
  42.                         } else if (typeof config === 'object') {
  43.                                 state.config = Object.assign(defaultConfig, config);
  44.                         }
  45.                 }
  46.         }
  47. }
  48. export default confirmModal
复制代码
组件内的参数从store获取,想要显示弹窗时调用this.$store.commit('SET_CONFIG', {}),第二个参数为弹窗设置内容。
全局注入

在main.js文件内注入组件:
  1. // 引入组件,请根据自己定义组件的实际路径和名称引入
  2. import ConfirmModal from './components/confirm-modal/confirm-modal.vue'
  3. Vue.component('confirm-modal', ConfirmModal)
  4. // 每次都通过$store调用过于繁琐,所以定义了一个全局方法
  5. Vue.prototype.$confirmModal = (config) => {
  6.         store.commit('SET_CONFIG', config)
  7. }
  8. // 获取小程序顶部状态栏高度
  9. const {
  10.         safeArea
  11. } = wx.getWindowInfo()
  12. Vue.prototype.$safeAreaTop = safeArea && safeArea.top || 0
复制代码
使用

  1. this.$confirmModal({
  2.         content: '请确认是否删除该条跟发规则?',
  3.         cancelText: '取消',
  4.         confirmText: '确认',
  5.         success: () => {}
  6. })
复制代码
调用后,结果如上图
附带:怎样在uniapp-H5项目中实现全局自定义弹窗

组件定义

组件的根本内容不变,重要是将弹窗设置项作为props转入,如下:

定义vue插件

在组件目录下定义index.js文件:
  1. import Vue from 'vue'
  2. import confirmModalVue from './confirm-modal.vue';
  3. // 定义插件对象
  4. const confirmModal = {};
  5. // vue的install方法,用于定义vue插件
  6. confirmModal.install = function(Vue, options) {
  7.         const confirmModalInstance = Vue.extend(confirmModalVue);
  8.         let currentMsg;
  9.         const initInstance = () => {
  10.                 // 实例化vue实例
  11.                 currentMsg = new confirmModalInstance();
  12.                 let msgBoxEl = currentMsg.$mount().$el;
  13.                 document.body.appendChild(msgBoxEl);
  14.         };
  15.         // 在Vue的原型上添加实例方法,以全局调用
  16.         Vue.prototype.$confirmModal = (options) => {
  17.                 if (!currentMsg) {
  18.                         initInstance();
  19.                 }
  20.                 const config = {
  21.                         content: '',
  22.                         btnType: 'default',
  23.                         cancelText: '取消',
  24.                         confirmText: '确定',
  25.                         cancelClass: '',
  26.                         confirmClass: '',
  27.                         showCancel: true,
  28.                         showConfirm: true,
  29.                         visible: true,
  30.                         success: null,
  31.                         cancel: null,
  32.                         title: '',
  33.                         closeEnabled: false,
  34.                         contentStyle: ''
  35.                 }
  36.                 if (typeof options === 'string') {
  37.                         Object.assign(currentMsg, config, {
  38.                                 content: options
  39.                         });
  40.                 } else if (typeof options === 'object') {
  41.                         Object.assign(currentMsg, config, options);
  42.                 }
  43.                 return currentMsg; // 为了链式调用
  44.         };
  45. };
  46. export default confirmModal;
复制代码
引入

在main.js内引入:
  1. import ConfirmModal from './components/confirm-modal'
  2. Vue.use(ConfirmModal)
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

来自云龙湖轮廓分明的月亮

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表