vue命令式组件的封装

一、前言

当Vue项目中ElementUIconfirm提示不满足我们的样式需求时,一般我们会修改全局样式,或者封装一个dialog弹窗组件用于消息的提示和操作。

如果封装一个dialog作为组件引入,必然需要一个visible变量来控制显隐,是否显示确认、取消按钮的变量及它们的回调函数,如果一个页面需要二次提示的地方太多,那就会显得模版臃肿、需要维护的变量变多,不优雅,使用成本变高。

xml 复制代码
 <!-- 是否取消订单 -->  
 <tips-dialog :visible.sync="dialogVisible.cancelTips" title="确认取消该订单吗?" :on-submit-c-b="cancelOrder" />  
 <!-- 是否删除订单 -->  
 <tips-dialog :visible.sync="dialogVisible.removeTips" title="确认删除该订单吗?" :message="删除后将无法恢复。" :on-submit-c-b="deleteOrder" />  
 ···
 ···

现在想让使用成本变低,可以考虑使用命令式组件的方式

二、命令式组件

命令式组件是通过编程的方式动态创建、挂载、销毁的

命令式组件的优点:

1、动态控制:可以根据用户行为或程序逻辑动态的创建和销毁组件。

2、灵活性:可以在代码任何部分创建组件爱你,并且可以动态传递参数或数据

3、代码隔离:有助于逻辑的封装和隔离

三、代码实践

弹窗vue模板

xml 复制代码
<template>  
  <div class="confirm-wrap">  
    <div class="main">  
      <div class="title">{{ title }}</div>  
      <p class="message">{{ message }}</p>  
      <div class="btn-grounp">  
        <button v-if="showCancelButton" class="cancel-btn" @click="$emit('cancel')">{{ cancelButtonText }}</button>  
        <button v-if="showConfirmButton" class="confirm-btn" @click="$emit('confirm')">{{ confirmButtonText }}</button>  
      </div>  
    </div>  
  </div>  
</template>

<style scoped lang="less">  
  .confirm-wrap {  
    position: fixed;  
    top: 0;  
    bottom: 0;  
    left: 0;  
    right: 0;  
    display: flex;  
    justify-content: center;  
    align-items: center;  
    background: rgba(0, 0, 0, 0.3);  
    .main {  
      width: 30%;  
      padding: 24px;  
      background: #fff;  
      border-radius: 3px;  
      .title {  
        color: #202d40;  
        font-size: 16px;  
      }  
      .message {  
        margin-top: 10px;  
        color: #899099;  
        font-size: 14px;  
      }  
      .btn-grounp {  
        display: flex;  
        justify-content: flex-end;  
        margin-top: 24px;  
      }  
      button {  
        box-sizing: border-box;  
        margin-left: 12px;  
        padding: 0px 22px;  
        font-size: 14px;  
        line-height: 32px;  
        cursor: pointer;  
      }  
      .confirm-btn {  
        color: #fff;  
        background: #006aff;  
      }  
      .cancel-btn {  
        color: #899099;  
        background: #fff;  
        border: 1px solid #edeef2;  
      }  
    }  
  }  
</style>

js部分,以$ygConfirm挂载到Vue的原型上

javascript 复制代码
import Vue from 'vue'  
import MessageBox from './index.vue'

const MessageBoxConstructor = Vue.extend(MessageBox)

const defualtOptions = {  
  confirmButtonText: '确定',  
  cancelButtonText: '取消',  
  showConfirmButton: true,  
  showCancelButton: true  
}

// 模拟elementUI的用法  
const confirm = function (message, title, options = {}) {  
  if (typeof title === Object && title!==null) {  
    options = title  
    title = ''
  }  
  options = { ...defualtOptions,  message, title , ...options)

  const instance = new MessageBoxConstructor({  
    data: options  
  })

  // 挂载到body上  
  instance.vm = instance.$mount()  
  document.body.appendChild(instance.vm.$el)

  // 销毁实例  
  const removeVM = () => {  
    instance.vm.$destroy()  
    document.body.removeChild(instance.vm.$el)  
  }

  // 监听确认和取消事件,由$emit触发  
  return new Promise((resolve, reject) => {  
    instance.vm.$on('confirm', () => {  
      resolve()  
      removeVM()  
    })  
    instance.vm.$on('cancel', () => {  
      reject()  
      removeVM()  
    })  
  })  
}

export default confirm

使用

javascript 复制代码
this.$ygConfirm('你好啊啊啊啊啊','test').then(()=>{
    console.log('点击了确认~')
}).catch(()=>{
    console.log('点击了取消~')
})

效果图

相关推荐
oil欧哟1 分钟前
🥳 做了三个月的学习卡盒小程序,开源了!
前端·vue.js·微信小程序
奶球不是球5 分钟前
el-table(elementui)表格合计行使用以及滚动条默认样式修改
前端·vue.js·elementui
liuyang___7 分钟前
vue管理布局左侧菜单栏NavMenu
前端·javascript·vue.js
前端Hardy32 分钟前
HTML&CSS&JS:必学!用粒子爆炸效果,让按钮点击 “告别枯燥”
javascript·css·html
前端Hardy35 分钟前
HTML&CSS&JS:必看!主题“自动换装”,10+风格随机切换超惊艳
javascript·css·html
打野赵怀真42 分钟前
render函数中return如果没有使用()会有什么问题?
前端·javascript
Scraper002443 分钟前
如何使用API和Node.js抓取Google新闻?
javascript
Riesenzahn43 分钟前
写一个左中右的满屏布局,左右固定220px,中间自适应并且要优先加载
前端·javascript
Riesenzahn44 分钟前
css在页面上画一个正方形,边长为页面宽度的一半
前端·javascript