项目实现|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')
        },    
相关推荐
神奇的程序员5 小时前
开发了一个管理本地开发环境的软件
前端·flutter
天若有情6736 小时前
程序员原创|借鉴JS事件冒泡,根治电脑文件混乱的“冒泡整理法”
开发语言·javascript·windows·ecmascript·电脑·办公·日常
XiYang-DING6 小时前
HTML 核心标签
前端·html
Csvn6 小时前
技术选型方法论
前端
Csvn7 小时前
前端架构演进:从页面到平台的十年变革
前端
李伟_Li慢慢7 小时前
ShaderToy-山峦+蓝天+白云
前端·webgl
小码哥_常7 小时前
Android字体字重设置全攻略:XML黑科技+Kotlin动态实现,告别.ttf臃肿
前端
FYKJ_20107 小时前
springboot校园兼职平台--附源码02041
java·javascript·spring boot·python·eclipse·django·php
言萧凡_CookieBoty8 小时前
AI 编程省 Token 实战:从 Spec、上下文工程到模型分层的降本策略
前端·ai编程
DFT计算杂谈9 小时前
wannier90 参数详解大全
java·前端·css·html·css3