项目实现|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')
        },    
相关推荐
嘟嘟0717几秒前
二叉树从入门到实战:四大遍历 + 递归思想详解
前端
渣波1 分钟前
全栈开发的“影分身”之术(mock):别再手动造数据了,你的 CRUD 不配让我等!
前端·javascript
亿元程序员2 分钟前
小伙伴说这个撕胶带游戏很火很解压,于是我连夜做了一个Cocos教程...
前端
如果超人不会飞2 分钟前
一文读懂 TinyRobot:前端 AI 组件库定位、价值与适用场景
前端·vue.js
如果超人不会飞4 分钟前
用TinyRobot Welcome组件打造贴心的AI助手欢迎页
前端·vue.js
悟空瞎说4 分钟前
Compose内嵌Flutter混合开发详解:页面嵌入、引擎缓存与双向通信完整实战
前端
如果超人不会飞6 分钟前
TinyRobot DragOverlay轻松实现AI对话中的拖拽上传
前端·vue.js
elirlove16 分钟前
打造属于自己的网页工匠台:HTML在线编辑器技术深度解析
前端·编辑器·html
wh_xmy9 分钟前
从HTML5到AI,我的前端十年
前端·程序人生·十年程序员·ai 对前端的影响
程序员mine12 分钟前
Web服务密码存储安全详解:从哈希到密钥派生的演进
前端·后端