Vue.js 跨层事件传递问题
我在
app.vue
里写了这么一个结构,打算通过
v-bind:is="view"
来切换不同的页面。
大概的结构是这样的:
app.vue
/ \
/ \
login.vue chat.vue
|
|
contentbox.vue
现在,我需要在
login.vue
上,向
contentbox.vue
发送一个数据,于是我使用事件来传递数据,通过
vm.$dispatch
和
vm.$broadcast
来往上和往下传播事件。
但是,当我在
login.vue
上把
app.vue
的 view 切换到
chat.vue
后,我发现
chat.vue
并不能接收到我传递的事件,更无法传递到
contentbox.vue
。
不明白这哪里出错了,或者大家有没有别的方法来传递数据呢?请各位指教指教。
以下是代码:
app.vue
<template>
<div class="container">
<div class="col-md-6 col-md-offset-3">
<component v-bind:is="view"></component>
</div>
</div>
</template>
<script>
module.exports = {
events: {
test: function (data) {
// app.vue 接收到下层传上来的 test 后,往下广播 test 事件
console.log('app.vue: got it.')
this.$broadcast('test', data)
return false
}
}
}
</script>
login.vue
<script>
module.exports = {
ready: function(){
// 监听 socket.io 的 login-success 事件
this.$root.socket.on('login-success', function(data){
this.$parent.view = 'chat'
history.pushState null, null, '#/chat'
// 切换页面后向上传播 test 事件
console.log('login.vue:sent')
this.$dispatch('test', data)
})
}
}
</script>
chat.vue
<template>
<inputbox></inputbox>
<contentbox></contentbox>
</template>
<script>
module.exports = {
events: {
test: function (data) {
console.log('chat.vue: got it.') // 并不能收到
}
}
}
</script>
contentbox.vue
<script>
module.exports = {
events: {
test: function (data) {
console.log('contentbox.vue: got it!') // 当然也到不了这里
console.log('data:', data)
return false
}
}
}
</script>
Answers
DOM上传数据这事大致有两种思路
一种是redux那一套,强调单向传递,虽然和react可能更容易整合,但实际上并没有强依赖react,应该可以和vuejs配合的。写代码比较无脑也比较啰嗦,但思路清晰不容易出问题
另一种传统的,也是题主用了的就是事件了。一般而言,想要把程序结构整理清楚的话,应该遵循的原则是上层通过引用、通过 方法调用 直接管理下层,而下层不关心上层,需要传递数据时通过 事件冒泡 向上传递状态。也就是事件一律往上走,方法调用一律往下调用。
vuejs我好久以前用的,印象里也没见过
$broadcast
这样的用法,总之向下扩散事件即使支持这个用法,也很容易导致整体结构混乱,不建议。
类似的还用向上引用,比如题主的
this.$parent.view = xxx
也是很容易导致混乱的实践(login这个组件只能在$parent.view = xxx有意义的地方创建了)。建议是login中触发login-success事件,app监听它创建的login组件的login-success,处理时调用chat组件的方法(比如刷新信息之类)
又比如我做一个dialog组件,里面可能会用
alert
、
confirm
这样的方法来显示对话框,然后会对外暴露
close
confirm-yes
之类的事件来告知调用dialog的人这个对话框的情况