项目场景:
(如下图)做后台的时候遇到的需求,点击按钮弹出弹窗,填写一些信息之后提交,因为弹窗中需要填写的信息太多,为了让本身这个页面代码不要过长,所以将弹窗单独封装成组件,通过父子传值来控制弹窗的打开和关闭
踩的坑:
使用props和$emit,作为父子之间的传值方式
- watch只在首次传值发生变化的时候起作用
- 子传父一直没起作用
原因分析:
仔细研究后发现,因为我用父组件传过来的值作为弹窗是否弹出的条件,弹出之后改变该值并传回去,但是因为**vue不推荐直接在子组件中修改父组件传来的props的值,是会报错的**,从而造成了子组件修改值不成功,所以父组件中该值并没有被改变,监听也不会起作用解决方案:
在子组件的生命周期created中定义一个新的值取代父组件出传过来的值就可以了,下面直接上代码
父页面,使用 import注册子组件,并定义
<template>
<div>
…………
// 自定义的组件**new-channel-dialog**,这个名字要和子组件的name相同mopenKey是传给子组件的值,
// loseNewChannel事件用于接收子组件的回调
<new-channel-dialog :open-key="openKey" @closeNewChannel="closeNewChannel" />
</div>
</template>
import newChannelDialog from './newChannelDialog.vue' // 这个路径看你自己写的位置
export default {
components: {
newChannelDialog
},
data() {
return {
openKey: 0, // 设置传值的初始值为0
…………
}
}
…………
// 这里写两个事件
// 打开弹窗事件,在点击按钮的时候触发,触发后改变openKey的值,传给子组件
openDialog() {
this.openKey = 1
},
// 关闭弹窗的回调
closeNewChannel(data) {
console.log(data) // 这里的data是子组件传回来的值,对应的就是子组件传过来的newOpenKey
this.openKey = data
}
}
子页面,
// 写props用于接收父组件的传值
export default {
props: {
openKey: {
type: Number, //类型
required: true
}
},
data() {
return {
newOpenKey: '', //定义一个新字段替换父组件传的字段
…………
}
},
// watch监听传值的变化
watch: {
openKey: {
deep: true,
immediate: true,
handler: function(val) {
if (val === 0) {
return // 为0的时候不做改变
} else if (val === 1) {
// 为1的时候唤醒弹窗
…………
}
}
}
},
// 在这里用新定义的字段替换传来的字段
created() {
this.newOpenKey = this.openKey
},
methods: {
// 关闭弹窗事件
closeNewChannel() {
this.newOpenKey = 0 // 将值改回初始
this.$emit('closeNewChannel', this.newOpenKey) // emit事件通知父组件
// 格式: this.$emit('父组件的事件名', '要传的值')
…………
},
…………
}