Vue自定义render统一项目组弹框功能

二、为什么要统一封装弹框;

要封装成怎样

通过举例常规弹框的写法。我们可以体会到,通常要弹出一个页面,需要创建一个页面 normalDialog.vue 包裹 dialogBody.vue (弹框主体);需要 parent.vue 设置flag控制弹框显示隐藏, normalDialog.vue 关闭的时候设置 parent.vue 对应 flag 。缺点: 流程繁杂、配置繁琐、不灵活、样式不统一和参数传递麻烦等 。如果一个项目弹框较多的时候,弊端将会更明显,大量的 isXxxDialogShow ,大量的 vue 文件。因此项目组急需一个能简单配置就能弹出弹框的 API 。

1. 常规弹框写法 dialoBody.vue (弹框主体) ,此处采用 Composition API 的写法。只做了简单的页面,包含校验,抽取保存数据的常规逻辑。

<template> <div> <div> <div>名称</div> <el-input v-model="name"></el-input> </div> <div> <el-radio-group v-model="attention"> <el-radio label="已关注"></el-radio> <el-radio label="等下关注"></el-radio> </el-radio-group> </div> <div> <el-radio-group v-model="like"> <el-radio label="已点赞"></el-radio> <el-radio label="等下点赞"></el-radio> </el-radio-group> </div> </div> </template> <script> import { reactive, toRefs } from '@vue/composition-api' import pick from 'lodash/pick' import { Message } from 'element-ui' export default { props: { defaultName: String, }, setup(props, ctx) { const ATTENTIONED = '已关注' const LIKED = '已点赞' const state = reactive({ name: props.defaultName, // 名称 attention: '已关注', // 关注 like: '已点赞', // 点赞 }) /************************************************************* * 页面绑定的事件 * 建议写法: * 1. 定义methods常量 * 2. 处理相关业务逻辑的时候,需要绑定事件到页面的时 * 建议通过methods.onXxx = ()=>{ // 相关逻辑 }的形式定义 * 好处1: onXxx定义的位置和相关业务逻辑代码关联一起 * 好处2: 可以统一通过...methods的形式在setup统一解构 * 好处3: 当页面逻辑复杂,需要操作的数据关联性强,不可拆解组件; * 可将相关业务的代码在独立模块定义; * 独立模块暴露API handleXxx(methods,state),流水线加工methods; * 和Vue2源码一样,流水线加工的思想. */ const methods = {} // 校验名称 methods.onNameBlur = () => {} // ************************ 向外暴露的API ************************ const apiMethods = { // 保存前校验 isCanSave() { if (state.attention !== ATTENTIONED || state.like !== LIKED) { Message.error('未关注或者点赞,不能关闭,嘻嘻') return false } return true }, // 获取保存数据 getSaveData() { // ******* lodash pick 从对象中抽取数据 return pick(state, ['name', 'attention', 'like']) }, } return { ...toRefs(state), ...methods, apiMethods, } }, } </script> <style lang="less"> .dialog-body { width: 100%; height: 100px; } </style>

2.normalDialog.vue 包裹弹框主体 dialoBody.vue

<template> <el-dialog title="帅哥,美女,我是标题" :visible.sync="isShow" :before-close="onClose" > <dialog-body default-name="参数传递的名称" ref="inner"></dialog-body> <span slot="footer"> <el-button @click="onClose">取 消</el-button> <el-button type="primary" @click="onOK">确 定</el-button> </span> </el-dialog> </template> <script> import dialogBody from './dialogBody.vue' export default { components: { dialogBody, }, data() { return { isShow: true, } }, methods: { onClose() { // *********** 修改parent.vue ******** this.$parent.isNormalDialogShow = false }, // ******* 控制保存流程 ******** onOK() { const inner = this.$refs.inner // 校验是否可以保存 if (inner.apiMethods.isCanSave()) { // 获取保存数据 const postData = inner.apiMethods.getSaveData() console.log('>>>>> postData >>>>>', postData) // 保存成功后关闭弹框 this.onClose() } }, }, } </script>

parent.vue

// html 部分 <normal-dialog v-if="isNormalDialogShow" /> // Js部分 data(){ isNormalDialogShow:false } methods:{ onDialogShow(){ // ******控制弹框显示***** this.isNormalDialogShow = true } }

2. 要封装成怎样

2.1 API诉求:

isXxxDialogShow el-dialog

2.2 理想API:

import dialogBody from './dialogBody.vue' const dialog = new JSDialog({ comonent: dialogBody, dialogOpts: { // 可扩展配置 title: 'JSDialog设置的弹框标题', width: '400px' }, props: { defaultName: 'JSDialog传递的参数', }, onOK() { const inner = dialog.getInner() // 能取到dialogBody的引用 // 控制流程 if (inner.apiMethods.isCanSave()) { // 获取保存数据 const postData = inner.apiMethods.getSaveData() console.log('>>>>> postData >>>>>', postData) // 关闭弹框 dialog.close() } }, onCancel() { dialog.close() // 弹框关闭 }, }) dialog.show() // 弹框显示

三、如何封装

动态控制显示内容,脑海浮现的三个方案: 卡槽、动态组件和重写 render 。下面在动态弹框场景下简单对比三个方案。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/f5d7b409e7b6605d5b3f8fba569d2047.html