项目实现|table中新增和修改复用drawer或者dialog

前端经常做的就是新增和修改表单提交,受组件化的影响,一般我们都会将表单进行复用,新增和修改共用一个drawer或者dialog。

接下来谈谈几种共用的方式

第一种方式: 组件的open由组件内部控制

子组件:

js 复制代码
    // template
    <el-drawer
            :title="title"
            :visible.sync="drawer"
            :before-close="close"
            custom-class="add-drawer">
        <el-form> 内容</el-form>
    </el-drawer>
    // data
    drawer: false,
    // methods
    open() {
        this.drawer = !this.drawer
    }, 

父组件:

父组件要做的事情:调用子组件的open、传递title的值、传递row的值

js 复制代码
    // template
    <add-drawer
        ref="addDrawer"
        :title="title"
        :row="row">
    </add-drawer>
    // methods
    addDrawer() {
        this.row = {}
        this.title = '新增'
        this.$refs.addDrawer.open()
    },
    editDrawer(row) {
        this.row = row
        this.title = '修改'
        this.$refs.addDrawer.open()
    },

此时如果在子组件直接处理row,像下面的代码是会出现:点击新增,drawer打开,el-form空白(合理);点击修改,drawer打开,el-form空白(不合理,本质应该有值)。

js 复制代码
    open() {
        this.drawer = !this.drawer
        if (JSON.stringify(this.row) !== '{}') {
            // 修改
            this.form = JSON.parse(JSON.stringify(this.row))
        } else {
            // 新增
            this.$refs.form && this.$refs.form.resetFields()
        }
    },

为什么会出现这个原因,是因为vue是异步更新的

txt 复制代码
父组件调用addDrawer() -> 调用子组件open方法并修改row -> 父组件重新渲染 -> 子组件重新获得props

在第二步,子组件拿不到新的row,所以提供了nextTick的解决方案:

js 复制代码
    open() {
        this.drawer = !this.drawer
        this.$nextTick(() => {
            if (JSON.stringify(this.row) !== '{}') {
                // 修改
                this.form = JSON.parse(JSON.stringify(this.row))
            } else { // 新增的时候 row是{}
                // 新增
                this.$refs.form && this.$refs.form.resetFields()
            }
        })
    },

nextTick是更新后再调用,那就可以在open中拿到最新的值

还有一种解决方案就是借助watch,在watch中进行逻辑处理

js 复制代码
    watch: {
        row: {
            immediate: true,
            deep: true,
            handler() {
                if (JSON.stringify(this.row) !== '{}') {
                    // 修改
                    this.form = JSON.parse(JSON.stringify(this.row))
                } else {
                    // 新增
                    this.$refs.form && this.$refs.form.resetFields()
                }
            }
        }
    },
 // methods       
   open() {
     this.drawer = !this.drawer
   }

第二种方式:不使用props传递,直接上参数

子组件:

js 复制代码
    // template
    <el-drawer
        :title="title"
        :visible.sync="drawer"
        custom-class="add-drawer">
    <el-form> 内容</el-form>
    </el-drawer>
    // data
    drawer: false,
    // methods
    open() {
        this.drawer = !this.drawer
    }, 

父组件:

js 复制代码
    addDrawer() {
        this.title = '新增'
        this.$refs.addDrawer.open()
    },
    editDrawer(row) {
        this.title = '修改'
        this.$refs.addDrawer.open(row)
    },

这样子组件处理数据,是必然可以拿到row的,因为row是通过参数传递的,不是通过props

js 复制代码
    // 子组件的open
        open(row) {
            this.drawer = !this.drawer
            if (row) {
                this.form = JSON.parse(JSON.stringify(row))
            } else { // 新增的时候 row是undefined
                this.$refs.form && this.$refs.form.resetFields()
            }
        },

第三种方式:组件的open由父组件控制

子组件:

js 复制代码
    //template
    <el-dialog
        :title="title"
        :visible.sync="dialogVisble"
        width="500px"
        @close="close"
        @open="open">
        <el-form> 内容</el-form>
    </el-dialog>
    // script
        props: {
            title: {
                type: String
            },
            visible: {
                type: Boolean
            },
            form: {
                type: Object
            }
        }   

父组件:

js 复制代码
    // template 
        <add-dialog
            ref="addDialog"
            :title="title"
            :visible="dialog"
            :form="row"
            @closed="close">
       </add-dialog>
    // methods
        addDialog() {
            this.title = '新增'
            this.row = {}
            this.dialog = true
        },
        editDialog(row) {
            this.title = '修改'
            this.row = row
            this.dialog = true
        },

子组件拿到父组件的值,需要做的操作

js 复制代码
    watch: {
        visible(v) {
            this.dialogVisble = v
        },
        form(v) {
            this.formData = JSON.parse(JSON.stringify(v))
        }
    },

子组件还处理了open和close回调方法,主要是为了解决form检验和关闭时报错子组件操作父组件数据的问题

js 复制代码
    // 如果没有open 那么出现一个问题,就是点击修改,一切正常,然后关闭。再点击新增,此时新增的校验会全部展示
    open() {
        this.$refs.form && this.$refs.form.resetFields()
    },
    // 如果没有close 那么会出现一个问题,就是点击dialog自带的x,会报错子组件修改父组件的错误,因为子组件的visible是父组件传值的,所以提交emit父组件去关闭
    close() {
            this.$emit('closed')
        },    
相关推荐
Highcharts.js8 小时前
如何使用Highcharts SVG渲染器?
开发语言·javascript·python·svg·highcharts·渲染器
We་ct8 小时前
LeetCode 228. 汇总区间:解题思路+代码详解
前端·算法·leetcode·typescript
爱问问题的小李8 小时前
ue 动态 Key 导致组件无限重置与 API 重复提交
前端·javascript·vue.js
码云数智-大飞8 小时前
从回调地狱到Promise:JavaScript异步编程的演进之路
开发语言·javascript·ecmascript
m0_748229998 小时前
PHP+Vue打造实时聊天室
开发语言·vue.js·php
子兮曰8 小时前
深入Vue 3响应式系统:为什么嵌套对象修改后界面不更新?
前端·javascript·vue.js
CHU7290358 小时前
直播商城APP前端功能全景解析:打造沉浸式互动购物新体验
java·前端·小程序
枫叶丹48 小时前
【Qt开发】Qt界面优化(一)-> Qt样式表(QSS) 背景介绍
开发语言·前端·qt·系统架构
子兮曰15 小时前
OpenClaw入门:从零开始搭建你的私有化AI助手
前端·架构·github
吴仰晖15 小时前
使用github copliot chat的源码学习之Chromium Compositor
前端