目的
Vue里是单向数据流,因此父组件传递子组件的参数,不能修改。如果尝试去修改,将会报错如下:
效果
双向通信
实现方式1
用$refs直接访问子组件的属性,由于读写的都是子组件本身,因此双向通信的问题一扫而光,不再报错。
父组件代码
1 2 3 4 5 6 7 | <el-button type="danger" @click="alert">$refs的方式</el-button> <my-alert ref="alert" /> methods: { alert() { this.$refs.alert.visual = true } } |
子组件代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <template> <el-dialog title="refs的方式" :visible="visual" :before-close="handleClose" > </el-dialog> </template> <script> export default { data() { return { visual: false, } }, methods: { handleClose() { this.visual = false } } } </script> |
实现方式2
使用props由父组件传值给子组件,这是正统做法,会稍稍麻烦一些,需要作双向通信
父组件代码
1 2 3 4 5 6 7 8 9 10 11 12 13 | <el-button type="success" @click="alert2">prop的方式</el-button> <your-alert :visual="visual" @hide="didHide" /> ... data() { return { visual: false } }, methods: { alert2() { this.visual = true } } |
这里通过visual参数,传递参数给子组件,同时@hide事件回调等待子组件传参回来
子组件代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <template> <el-dialog title="prop的方式" :visible="dialogVisible" :before-close="handleClose" > </el-dialog> </template> <script> export default { props: ['visual'], data() { return { dialogVisible: this.visual } }, watch: { visual(val) { this.dialogVisible = val; } }, methods: { handleClose() { console.log('is closing') const state = false this.dialogVisible = state // 向父组件传值 this.$emit('hide', state) } } } </script> |
首先子组件通过props定义了一个属性,用来接收父组件的传参,
这里还需要watch监听传来的props值,来改变我们子组件局部变量,即时刷新界面,也就是这里的弹窗才可以弹出。
最后,当点击关闭后,要通过你父组件更新其visual的值为false,需要关闭后,无法通过再次点按钮弹出窗口,父组件会误以为visual一直是true。
实现方式3
由于这个例子就是要控制弹窗的显示与关闭,那么大可不必这么麻烦,子组件包含button的方式,visual的可见性true|false全凭子组件负责,已经不存在通信的问题了,比第一种方式还要简单粗暴。
父组件代码
1 | <her-alert /> |
子组件代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <template> <div> <el-button type="primary" @click="show">子组件包含button的方式</el-button> <el-dialog title="子组件包含button的方式" :visible="dialogVisible" :before-close="handleClose" > </el-dialog> </div> </template> <script> export default { data() { return { dialogVisible: false } }, methods: { show() { this.dialogVisible = true }, handleClose() { this.dialogVisible = false } } } </script> <style scoped> div { margin-top: 20px; } </style> |
总结
第1种,是通用解
第2种,早晚要派上用场
第3种,是特殊场景解法
关注我
欢迎关注订阅号【黄秀杰】
mp