vue组件封装

 需求:很多场景,如confirm或者弹出的输入框,都需要后续做处理,之前自己简单的传入一个  
 回调函数觉得代码不好维护,遂想到使用Promise对象封装,调用之后返回一个Promise对象,  
 我们就可以用自己熟悉瑐Promise方式做后续的操作了!

组件实现思路

  • 正常创建一个对象,在对象原型上拓展一个回调方法callbackFn,我们后边操作的时候调用
  • 在创建对象那里返回一个Promise对象
  • 新建一个变量,保存Promise对象的resolvereject方法
  • 创建一个vue对象,挂在到dom并添加到页面
  • 我们在用户操作以后根据不同值,调用callbackFn的时候传入不同的参数
  • 最后我们在callbackFn函数中根据不同的传参,触发之前保存的Promise对象的resolvereject方法

下边是代码,我以地区选择插件作为示例

  • vue模板代码
<template>
    <section class="city-select" :class="{animation: !show}">
      <div class="city-select-content">
        <h2 class="city-select-title"> 
        请选择地址<i class="icon-close" @click="hide">x</i> 
        </h2>
        <v-distpicker 
        type="mobile" 
        @province="changeProive"  
        @city="changeCity" 
        @area="changeArea
        "></v-distpicker>
      </div>
      <button class="btn-confirm" @click="confirm">确定</button>
    </section>
</template>
<script>
  • css
//因为是封装的移动端组件 所以使用rem,不要问我rem是什么 ,我也不知道
<style lang="less">
    .city-select{
        &{
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, .5);
        }
        .city-select-content{
            position: absolute;
            left: 0;
            bottom: 3.0625rem;
            width: 100%;
            height: 22.25rem;
            overflow: scroll;
            background: #fff;
        }
        .btn-confirm{
            position: absolute;
            bottom: 0;
            width: 100%;
            height: 3.0625rem;
            color: #fff;
            font-size: 0.875rem;
            background-color: #5556ab;
            border-radius: 0;
        }
        .city-select-title{
            height: 2.5rem;
            line-height: 2.5rem;
            font-size: 1.0rem;
            border-bottom: 1px solid #5556ab;
            text-indent: 0.625rem;
            color: #323232;
        }
        .icon-close{
            float: right;
            display: inline-block;
            width: 2.5rem;
            height: 2.5rem;
            font-size: 1.875rem;
            line-height: 2rem;
            color: #5556ab;

        }
    }
</style>
  • 模板 js部分
<script>
import Distpicker from 'v-distpicker'

export default{
  data () {
    return {
        show: true,//当前组件是否显示
        province: '',//省
        city: '',//市
        area: ''//区
    }
  },
  components: {
    'v-distpicker': Distpicker
  },
  methods: {
    changeProive(province) {
        //每次省份改变的时候清空 市和区的值
        this.province = province
        this.city = ''
        this.area = ''
    },
    changeCity(city) {
    //每次城市改变的时候清空区的值
        this.city = city
        this.area = ''
    },
    changeArea(area) {
        //赋值当前用户选择的区域
      this.area = area
    },
    hide() {
        //关闭方法,通过this.show 给wrap添加class animation,隐藏当前组件
        //调用原型的callBack方法
        this.show = false;
        this.callBack && this.callBack(false)
    },
    confirm () {
        //确认方法
        //拼接用户选择的地址为字符串
        let self = this;

        if(!self.province) return this.$Toast('请选择地址')
        if(!self.city) return this.$Toast('请选择城市')
        if(!self.area) return this.$Toast('请选择市区')
        let addr= `${self.province.value} ${self.city.value} ${self.area.value} `
        self.show = false;
        //不为空的话就返回当前地址addr
        self.callBack && self.callBack(addr)
    }
  }
}
</script>

封装方法,实现js调用

/**
 * @description  地址选择插件
 * 依赖插件 v-distpicker
 * 安装 npm install v-distpicker --save
 * 挂在到全局 
 * import cityPicker from '@/components/common/city-selected.js'
 * Vue.$cityPicker = Vue.prototype.$cityPicker = window.$cityPicker = cityPicker;
 * 调用方式  返回一个Promise对象
 * this.$cityPicker()
    .then(res=>{
      console.log('res', res)
    })

 *注:文件引用一定要使用import的方式,使用require的话会加载模板失败
 *导致创建的对象模板没有 内容
 */

import Vue from 'vue'
import citySelectTem from './city-selected.vue'
let currentMsg = null //保存Promise的resolve和reject方法
let instance = null //创建实例的时候使用

const Constructor = Vue.extend(citySelectTem)
//删除dom节点方法
const removeDom = event => {
    event.target.parentNode.removeChild(event.target)
}
function citySelect (option = {}) {
    //给当前对象的原型添加callBack方法
    Constructor.prototype.callBack = defaultCallBack
    //创建并挂在组件
    instance = new Constructor().$mount(document.createElement('div'))
    //将组建添加到body
    document.body.appendChild(instance.$el)
    //让当前实例监听animationend事件,就是我们在给元素添加animation的时候会触发
    instance.$el.addEventListener('animationend', removeDom, false)
    // 弹出层再次隐藏时时销毁组件

    return new Promise((resolve, reject) => {
            //使用变量保存两个参数,后边调用
            currentMsg = { resolve, reject }
        })
}
//父元素的callBack方法
function defaultCallBack (action) {
    if(!action) currentMsg.reject('cancel')
    currentMsg.resolve(action)
}

export default citySelect

总结

都是很简单的知识,原型继承,Promise的使用,没有特别高深的知识,个人也是通过思考和学习发 
现要多变通,才能编写出更优雅瑐组件,还有就是有很多很优秀的jquery插件 ,我们可以使用vue  
封装使用,当然现在因为自己还是渣渣水平,代码质量不好,大神看到了记得吐槽
Logo

前往低代码交流专区

更多推荐