美文网首页
从vue2插件到vue3插件

从vue2插件到vue3插件

作者: susu一口酥 | 来源:发表于2021-04-21 15:09 被阅读0次

主要总结确认弹窗组件(comfirm)的封装,和插件封装的主要知识点

共同点

1.都需要要一个已经实现的comfirm.vue组件文件(以下是组件在vue2中的实现)

<template>
  <div class="comfirm-box" v-show="modelShow">
    <transition name="fade">
      <div class="comfirm" v-if="show">
        <div class="btn-close" @click="cancelEvent" v-if="showCloseBtn"></div>
        <h4 class="title" v-if="!hideTitle">{{title}}</h4>
        <div class="message"
          :class="{'message-add' : addMessageDistance}" 
          v-html="content"></div>
        <div class="btn-box" :class="{'btn-box-center':hideCancel}">
          <!-- 取消按钮 -->
          <div class="btn btn-cancel" 
            :style="{fontSize : (btnFontSize || '' )}" 
            @click="cancelEvent"
            v-if="!hideCancel">
              {{cancelText || '取消'}}
          </div>
          <!-- 确定按钮 -->
          <div class="btn btn-submit" 
            :style="{fontSize : (btnFontSize || '' )}"
            :class="{'big-btn-submit':hideCancel}" 
            @click="onOkEvent">
              {{okText || '确定'}}
          </div>
        </div>
      </div>
    </transition>
  </div>
</template>
 
<script>
  import {debounce} from '@/utils/utils';
  let that;
  export default {
    name: 'comfirm',
    props : {
      //标题
      title : {
        type : String
      },
      // 内容
      content : {
        type : String
      },
      //是否隐藏标题
      hideTitle : {
        type : Boolean,
        default : false
      },
      //取消按钮文本
      cancelText : {
        type : String,
        default : '取消'
      },
      //隐藏取消按钮
      hideCancel : {
        type : Boolean,
        default : false
      },
      // 确定按钮文案
      okText : {
        type : String,
        default : '确定'
      },
      //v-model对外开放值
      value : {
        type : Boolean
      },
      //按钮字体字号
      btnFontSize : {
        type : String
      },
      //显示关闭按钮
      showCloseBtn : {
        type : Boolean
      }
    },
    data(){
      that = this;
      return{
        //显示弹窗
        modelShow : this.value,
        show : false,
        //判断是否是通过方法调用
        isComfirm : false
      }
    },
    mounted(){},
    computed:{
      //增加文本间距
      addMessageDistance(){
        let {showCloseBtn,hideTitle} = this;
        //显示关闭按钮,并且隐藏标题,则增加段落文本距离顶部距离
        return (showCloseBtn && hideTitle);
      }
    },
    methods:{
      //确认事件
      onOkEvent : debounce(()=>{
        let {onOk} = that;
        //判断是否有确认回调,如果有的话执行
        onOk && onOk();
        //提交父组件确认事件
        that.$emit('on-ok');
        //关闭弹窗
        that.close();
      },false),
      //取消事件
      cancelEvent : debounce(()=>{
        let {onCancel} = that;
        //判断是否有取消回调
        onCancel && onCancel();
        try{
          //提交父组件取消事件
          that.$emit('on-cancel');
        }
        catch(err){
          console.log(err);
        }
        //关闭弹窗
        that.close();
      },false),
      // 关闭弹窗
      close(){
        let {isComfirm} = this;
        //隐藏弹窗
        this.modelShow = false;
        if(isComfirm){
          setTimeout(()=>{
            // 彻底销毁实例
            that.$destory && that.$destory();
            //删除节点
            if(that.$el && document.body.contains(that.$el)){
             that.$el.remove()
            }
          },100);
        }
      }
    },
    watch : {
      //监听外部值变化,赋值给模板显隐
      value(modelShow){
        this.modelShow= modelShow;
      },
      //监听显隐变化传递给外层组件
      modelShow(value){
          this.$nexttick(()=>{
              this.show = value;
              this.$emit('input',value);
          })
      }
    }
  }
</script>
 
<style lang="scss" scoped>
  .comfirm-box{
    width: 100%;
    height: 100vh;
    overflow: hidden;
    background-color: rgba(0,0,0,0.3);
    position: fixed;
    left: 0;
    top: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 11;
  }
  .comfirm{
    padding: 40px;
    border-radius: 32px;
    background-color: #fff;
    width: 600px;
    max-height: 70vh;
    box-sizing: border-box;
    text-align: center;
    overflow-y: auto;
    position: relative;
  }
  .btn-close{
    width: 85px;
    height: 85px;
    background: url(../../assets/components/comfirm/close.png) no-repeat;
    background-position: center center;
    position: absolute;
    right: 0;
    top: 0;
  }
  .title{
    font-size: 38px;
    color: #353535;
    line-height: 50px;
  }
  .message{
    font-size: 28px;
    color: #353535;
    line-height: 36px;
  }
  .message-add{
    margin-top: 30px;
  }
  .btn-box{
    display: flex;
    justify-content: space-around;
    margin-top: 36px;
  }
  .btn-box-center{
    justify-content: center;
  }
  .btn{
    min-width: 240px;
    max-width: 250px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 22px;
    height: 92px;
    line-height: 44px;
    font-size: 34px;
    border: 2px solid transparent;
    border-radius: 44px;
    box-sizing: border-box;
  }
  .btn-cancel{
    border-color: #EAEAEA;
    color: #737373;
    background-color: #FFFFFF;
  }
  .btn-submit{
    background: #FFD321;
    border-color: #FFD321;
    color: #282121;
  }
  .big-btn-submit{
    width: 320px;
    max-width: 320px;
  }
  .fade-enter-active, .fade-leave-active {
    transition: all .3s;
  }
  .fade-enter /* .fade-leave-active below version 2.1.8 */ {
    transform: scale(0.3);
    opacity: .8;
  }
  .fade-leave-to{
    transform: scale(0.8);
    opacity: .8;
  }
</style>
 

不同点

1. vue3中使用comfirm.vue文件(功能不变的情况),有几个地方是需要改动的

//props中要增加onCancel、onOk方法的定义
//把data中的isComfirm参数移到 props中
props : {
    //取消事件
    onCancel : {
        type : Function
    },
    //确认事件
    onOk : {
        type : Function
    },
    //是否为插件调用
    isComfirm : {
        type : Boolean
    }
}

//动画样式改动
//vue3取消了 .fade-enter和.fade-leave-to
//.fade-enter-active, .fade-leave-active 样式重新调整如下
.fade-enter-active{
    animation: moveIn .3s;
}
.fade-leave-active {
    animation: moveOut .3s;
}
@keyframes moveIn{
    from{
      transform: scale(0.3);
      opacity: .8;
    }
    to{
      transform: scale(1);
      opacity: 1;
    }
}
@keyframes moveOut{
    from{
      transform: translateY(0);
      opacity: 1;
    }
    to{
      transform: translateY(100%);
      opacity: 0;
    }
}

2.入口文件不同

以下是vue2的入口文件
import Vue from 'vue';
//引入确认弹窗组件
import comfirm from './comfirm.vue';

// 创建一个vue子类
const ComfirmConstructor = Vue.extend(comfirm);

const Comfirm = ({
  title='',
  content='',
  hideTitle,
  hideCancel,
  cancelText,
  okText,
  onOk,
  btnFontSize,
  onCancel,
  showCloseBtn
}={}) => {
  //实例化组件
  const ComfirmInstance = new ComfirmConstructor({
    data : {
      isComfirm : true
    }
  });

  ComfirmInstance.vm = ComfirmInstance.$mount();

  {
    //赋值外部传进来的数据
    //参数定义在组件内查看
    ComfirmInstance.title = title;
    ComfirmInstance.content = content;
    ComfirmInstance.hideTitle = Boolean(hideTitle);
    ComfirmInstance.hideCancel = Boolean(hideCancel);
    ComfirmInstance.btnFontSize = btnFontSize;
    //显示关闭按钮
    ComfirmInstance.showCloseBtn = Boolean(showCloseBtn);
    if(cancelText){
      ComfirmInstance.cancelText = cancelText + '';
    }
    if(okText){
      ComfirmInstance.okText = okText + '';
    }
    //赋值确定按钮回调事件
    if(onOk && typeof onOk === 'function'){
      ComfirmInstance.onOk = onOk;
    }
    //取消回调事件
    if(onCancel && typeof onCancel === 'function'){
      ComfirmInstance.onCancel = onCancel;
    }
  }

  // 控制组件的显隐
  ComfirmInstance.modelShow = true;

  //获取dom
  ComfirmInstance.dom = ComfirmInstance.vm.$el;
  //往body里增加弹窗
  document.body.appendChild(ComfirmInstance.dom);

  return ComfirmInstance.vm;
} 

export default{
    //导出安装的文件
  install : (vue) => {
    vue.prototype.$comfirm = Comfirm;
  }
}

/* 
使用说明 

第一种方式
在main.js中引入
import Comfirm from './components/comfirm';
Vue.use(Comfirm);

在业务模块通过方法调用
this.$comfirm({
  // hideTitle 是否隐藏头部,默认为false
  // hideCancel 是否隐藏取消按钮,默认为false
  content : '内容字符串,可以是带html结构的',
  cancelText : '取消按钮文案,默认是取消',
  okText : '确认按钮文案,默认是确认',
  //成功回调,可以不设置
  onOk(){
    console.log('xixihaha ')
  },
  //取消回调,可以不设置
  onCancel(){
    console.log('取消')
  }
})

第二种方式
在需要使用的页面作为组件引用
import comfirm from '../../components/common/comfirm/comfirm.vue';
<comfirm title="标题" content="内容" v-model="showComfirm"></comfirm>

value   对话框是否显示,可使用 v-model 双向绑定数据。   Boolean   false
title   标题
content 内容
ok-text   确定按钮文字  String  确定
cancel-text   取消按钮文字  String  取消
on-ok   点击确定的回调   
on-cancel   点击取消的回调
hide-title 隐藏标题
hide-cancel 是否隐藏取消按钮,默认为false
*/
以下是vue3的入口文件
import { createVNode, render } from 'vue';
//引入确认弹窗组件
import comfirm from './comfirm.vue';

const Comfirm = function(options:any={}){
  // 判断是否已经有节点
  const comfirmDom = document.getElementById('comfirm-box');
  //如果有节点删除
  if(comfirmDom && document.body.contains(comfirmDom)){
    document.body.removeChild(comfirmDom);
  }
  //定义是插件形式调用
  options.isComfirm = true;
  //显示弹窗
  options.value = true;
  //创建虚拟dom
  const vm:any = createVNode(comfirm,options);
  const container = document.createElement('div');
  container.id = 'comfirm-box';
  //执行渲染函数
  render(vm,container);
  //往body增加节点
  document.body.appendChild(container);
}

export default{
  install : (app:any) => {
    app.config.globalProperties.$comfirm = Comfirm;
  }
}

/* 
使用说明 

第一种方式
在main.js中引入
import Comfirm from './components/common/comfirm';
Vue.use(Comfirm);

在业务模块通过方法调用
this.$comfirm({
  // hideTitle 是否隐藏头部,默认为false
  // hideCancel 是否隐藏取消按钮,默认为false
  content : '内容字符串,可以是带html结构的',
  cancelText : '取消按钮文案,默认是取消',
  okText : '确认按钮文案,默认是确认',
  //成功回调,可以不设置
  onOk(){
    console.log('xixihaha ')
  },
  //取消回调,可以不设置
  onCancel(){
    console.log('取消')
  }
})

第二种方式
在需要使用的页面作为组件引用
import comfirm from '../../components/common/comfirm/comfirm.vue';
<comfirm title="标题" content="内容" v-model="showComfirm"></comfirm>

value   对话框是否显示,可使用 v-model 双向绑定数据。   Boolean   false
title   标题
content 内容
ok-text   确定按钮文字  String  确定
cancel-text   取消按钮文字  String  取消
on-ok   点击确定的回调   
on-cancel   点击取消的回调
hide-title 隐藏标题
hide-cancel 是否隐藏取消按钮,默认为false
*/

注意点

1.在vue3中的setup使用

import {getCurrentInstance} from 'vue';

setup(){
    const {ctx}:any = getCurrentInstance();
    ctx.$comfirm({
      // hideTitle 是否隐藏头部,默认为false
      // hideCancel 是否隐藏取消按钮,默认为false
       content : '内容字符串,可以是带html结构的',
       cancelText : '取消按钮文案,默认是取消',
      okText : '确认按钮文案,默认是确认',
      //成功回调,可以不设置
      onOk(){
        console.log('xixihaha ')
      },
      //取消回调,可以不设置
      onCancel(){
        console.log('取消')
      }
  });
}

相关文章

网友评论

      本文标题:从vue2插件到vue3插件

      本文链接:https://www.haomeiwen.com/subject/rvhzlltx.html