• vue弹窗插件实战


    vue做移动端经常碰到弹窗的需求, 这里写一个功能简单的vue弹窗

    popup.vue

    
    <template>
      <div class="popup-wrapper" v-show="visible" @click="hide">
        <div class="popup-text">{{text}}</div>
      </div>
    </template>
    

    组件html结构, 外层divposition:fixed定位, 内层div显示弹窗内容

    
    export default {
      name: 'popup',
      props: {
        text: { //文字内容
          type: String,
          default: ''
        },
        time: { //显示的时长
          type: Number,
          default: 3e3
        },
      },
      data(){
        return {
          visible: false
        }
      },
      methods: {
        open() {
          this.visible = true
          clearTimeout(this.timeout);
          this.$emit('show')
          if(this.time > 0){
            this.timeout = setTimeout(() => {
              this.hide()
            }, this.time)
          }
        },
        hide() {
          this.visible = false
          this.$emit('hide')
          clearTimeout(this.timeout);
        }
      }
    }
    

    popup.vue只有2个属性: 文本和显示时间。组件显示隐藏由内部属性visible控制,只暴露给外界open和hide2个方法,2个方法触发对应的事件

    测试一下

    
    <template>
      <popup ref="popup" text="弹窗内容" :time="1e3"></popup>
    </template>
    <script>
    import Popup from '@/components/popup'
      ...
        this.$refs.popup.open()
       ...
    </script>
    

    在这里插入图片描述

    插件化

    组件功能写好了,但是这种调用方式显得很累赘。举个例子layer.js的调用就是layer.open(...)没有import,没有ref,当然要先全局引用layer。我们写的弹窗能不能这么方便呢,为此需要把popup改写成vue插件。
    说是插件,但能配置属性调用方法的还是组件本身,具体是实例化的组件,而且这个实例必须是全局单例,这样不同vue文件唤起popup的时候才不会打架

    生成单例

    
    // plugins/popupVm.js
    import Popup from '@/components/popup'
    let $vm
    export const factory = (Vue)=> {
      if (!$vm) {
        let Popup = Vue.extend(PopupComponent)
        $vm = new Popup({
          el: document.createElement('div')
        })
        document.body.appendChild($vm.$el)
      }
      return $vm
    }
    

    组件实例化后是添加在body上的,props不能写在html里需要js去控制,这里写个方法让属性默认值继续发挥作用

    
    // plugins/util.js
    export const setProps = ($vm, options) => {
      const defaults = {}
      Object.keys($vm.$options.props).forEach(k => {
        defaults[k] = $vm.$options.props[k].default
      })
      const _options = _.assign({}, defaults, options)
      for (let i in _options) {
        $vm.$props[i] = _options[i]
      }
    }
    
    
    // plugins/popupPlugin.js
    import { factory } from './popupVm'
    import { setProps } from './util'
    
    export default {
      install(Vue) {
         let $vm = factory(Vue);
    
         const popup = {
          open(options) {
            setProps($vm, options)
            //监听事件
            typeof options.onShow === 'function' && $vm.$once('show', options.onShow);
            typeof options.onHide === 'function' && $vm.$once('hide', options.onHide);
            $vm.open();
          },
          hide() {
            $vm.hide()
          },
          //只配置文字
          text(text) {
            this.open({ text })
          }
        }
        
        Vue.prototype.$popup = popup
      }
    }
    

    在main.js内注册插件

    
    //main.js
    import Vue from 'vue'
    import PopupPlugin from '@/plugins/popupPlugin'
    
    Vue.use(PopupPlugin)
    

    在vue框架内调用就非常方便了

    
    <script>
      ...
        this.$popup.text('弹窗消息')
      ...
    </script>
    

    来源:https://segmentfault.com/a/1190000016313195

  • 相关阅读:
    使用 %matplotlib inline 出错?
    RandomForest 调参
    sql中的笛卡尔积
    Sublime text 3 搭建Python3 IDE
    在Windows Python3.5 安装LightGBM
    lodash获取数组或对象的值 at
    lodash 移除数据元素 pull without 删除数组元素
    js 常用类型转换简写
    UTC时间格式转换
    CSS Flexible 布局兼容性以及解决方案
  • 原文地址:https://www.cnblogs.com/qixidi/p/10143798.html
Copyright © 2020-2023  润新知