likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 8

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

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

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

子组件:

    // 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的值

    // 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空白(不合理,本质应该有值)。

    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是异步更新的

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

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

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

    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中进行逻辑处理

    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
   }

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

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

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

子组件:

    // 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
    }, 

父组件:

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

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

    // 子组件的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由父组件控制

子组件:

    //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
            }
        }   

父组件:

    // 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
        },

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

    watch: {
        visible(v) {
            this.dialogVisble = v
        },
        form(v) {
            this.formData = JSON.parse(JSON.stringify(v))
        }
    },

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

    // 如果没有open 那么出现一个问题,就是点击修改,一切正常,然后关闭。再点击新增,此时新增的校验会全部展示
    open() {
        this.$refs.form && this.$refs.form.resetFields()
    },
    // 如果没有close 那么会出现一个问题,就是点击dialog自带的x,会报错子组件修改父组件的错误,因为子组件的visible是父组件传值的,所以提交emit父组件去关闭
    close() {
            this.$emit('closed')
        },    

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

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