我很希望项目中可以多接触一些新东西,实践出真知,对于编程来说就是要多动手,多总结几录,多思考,才能更好的避坑,因为动手了会发现好多你以为的不是你以为的。
概述
PC 端项目中,一直使用的是Element UI ,最近功能迭代,有一个选择专家的弹窗在多个页面应用到,因此需要将dialog进行封装以便复用,在Element-UI 的基础上,对dialog 进行封装,最重要的是一个属性值的控制 即 visible,对于dialog 中要显示哪些内容,按照一般组件传过来就可以了。
核心问题
el-dialog 的 visibile 属性值 只能在父组件或者子组件中一个进行修改,父组件传给子组件的属性值不能在子组件中直接进行修改,这是VUE 比较介意的。如果在子组件中直接修改就会报以下错误。
vue.runtime.esm.js?2b0e:619 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "dialogFormVisible"
found in
---> <MyDialog> at src/views/packageDialog/MyDialog.vue
<DialogDemo> at src/views/packageDialog/dialogDemo.vue
<App> at src/App.vue
<Root>
问题解决
父组件传给dialog 子组件的 属性值 不直接使用在visible 属性值上,取另外的值与其同步
在dialog 子组件中 通过watch 监听父组件中传值的变化,进行同步
子组件中需要关闭dialog 时,同样要触发父组件中的时间,修改父组件中定义的控制dialog 显示的值
核心代码如下:
dialogShow(val) {
this.dialogFormVisible = val
}
},
methods: {
closeDialog() {
this.$emit('dialogShowChange', false)
}
}
整体Demo 代码
父组件:
<template>
<div class="dialogDemoContainer">
<el-button type="primary" @click="dialogShowChange(true)">show dialog</el-button>
<div v-if="dialogShow" class="dialogBox">
<myDialog :dialogShow="dialogShow" @dialogShowChange="dialogShowChange"></myDialog>
</div>
</div>
</template>
<script>
import myDialog from './MyDialog.vue'
export default {
data() {
return {
dialogShow: false
}
},
components: {
myDialog
},
methods: {
dialogShowChange(val) {
this.dialogShow = val
}
}
}
</script>
<style lang="scss" scoped>
.dialogDemoContainer {
text-align: center;
padding: 20px;
.dialogBox {
text-align: left;
}
}
</style>
dialog 子组件:
<template>
<el-dialog title="收货地址" :visible.sync="dialogFormVisible" @close="closeDialog">
<el-form :model="form">
<el-form-item label="活动名称" :label-width="formLabelWidth">
<el-input v-model="form.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="活动区域" :label-width="formLabelWidth">
<el-select v-model="form.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="closeDialog">取 消</el-button>
<el-button type="primary" @click="closeDialog">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
export default {
props: {
dialogShow: {
type: Boolean,
default: false
}
},
data() {
return {
dialogFormVisible: this.dialogShow,
form: {
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: ''
},
formLabelWidth: '120px'
}
},
watch: {
dialogShow(val) {
this.dialogFormVisible = val
}
},
methods: {
closeDialog() {
this.$emit('dialogShowChange', false)
}
}
}
</script>
<style lang="scss" scoped>
</style>
最终,要记住问题得本质,及这类问题得解决,希望不断采坑不断进步。