项目实现|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')
        },    
相关推荐
IT女孩儿1 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡2 小时前
commitlint校验git提交信息
前端
天天进步20152 小时前
Vue+Springboot用Websocket实现协同编辑
vue.js·spring boot·websocket
虾球xz2 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇3 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒3 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员3 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐3 小时前
前端图像处理(一)
前端
程序猿阿伟3 小时前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
疯狂的沙粒3 小时前
对 TypeScript 中函数如何更好的理解及使用?与 JavaScript 函数有哪些区别?
前端·javascript·typescript