VueJS 连接不相关的(如 parent/child)组件
VueJS connect unrelated (as in parent/child) components
我正在探索 vue.js 并且对如何解决某个问题有疑问。
我的根组件具有以下模板:
<div class="container">
<div class="stage">
<map :current-time="currentTime" :recording="recording"></map>
<player :track="track" :current-time="currentTime"></player>
</div>
<control-panel :current-time="currentTime"></control-panel>
</div>
基本上,<player>
组件内部有 <video>
元素,它将加载指定的轨道(隐藏本机控件)。因此,它实际上会在视频播放时驱动应用程序的状态(当前时间、播放状态等)。但是,<control-panel>
具有指示视频状态的滑动条和按钮(play/pause,搜索)。显然,改变其中一个组件的一般状态会影响其他两个组件(地图也会根据当前时间进行处理)。
但是,我想知道这是否更有意义,以及 Vue 是否支持提供对组件的引用,以便我可以为 <control-panel>
提供对 <player>
的引用,以便它可以进行状态更改直接来自它。
或者应该以某种 global-state-passed-down-to-children 或 event-broadcast 的方式完成?在纠正我之前,请考虑一个示例,其中有两个 <player>
s 和两个 <control-panel>
s 在层次结构上不相关,但是一个 panelA 与 playerA 一起工作,而 panelB 与 playerB 一起工作。在这种情况下,我认为广播选项会掉落 table,对吗?
欢迎任何建议,尤其是在我刚刚学习 Vue 的时候。
更新 1
因此,在更加熟悉 Vue 并听取社区的反馈后,我想我想出了一个将 <player>
和 <control-panel>
同步在一起的聪明解决方案。我的标记更改为以下内容:
<div class="container">
<div class="stage">
<map :current-time="currentTime" :recording="recording"></map>
<player :track="track" :current-time="currentTime" v-ref:player></player>
</div>
<control-panel :current-time="currentTime" v-ref:player-controls :player="$refs.player"></control-panel>
</div>
注意 v-ref
属性添加到 <player>
和 <control-panel>
以及后者的 :player="$refs.player"
属性。这使我能够在逻辑上将一个与另一个联系在一起。在我看来,控制面板知道它在控制谁或什么是有意义的。我打算进一步测试它,但就目前而言,这似乎有效。
至于捆绑 <map>
,我将最终使用广播或简单地 two-way currentTime
由 <control-panel>
更新。我会随时更新此 post,如果与任何答案不同,我会标记正确答案或 post 我自己的答案。
更新 2
阅读下面我的回答。我已经能够使用以下方法成功解决我的问题。
我认为将它们作为独立的组件保留是个好主意;
然后您可以随时切换控制面板组件,使用另一个使用相同界面
(就像在电子商务应用程序中将 Stripe 换成其他支付处理器一样)
$broadcasting
和 $dispatching
即使有多个玩家在场也能正常工作,只要您为每个 broadcast/dispatch 传递一个标识符键,以便接收消息的每个组件可以立即确定如果是送给他们的。
解决方案涉及采用 更新 1 中描述的方法。因为 <video>
元素经过 API 的深思熟虑,将其转换为响应式组件相当容易(尽管很烦人)。
视频元素的包装器最终以下列方式创建了几个 computed
属性:
'currentTime': {
cache: false,
get: function () {
return this.$els.player.currentTime;
},
set: function (value) {
this.$els.player.currentTime = value;
}
}
属性 cache: false
必须使用,因为该属性未绑定到反应式元素,并且每次查询该属性时都需要重新计算。
不让组件完全反应是故意的。也就是说,我可以将需要的属性定义为 props
,并假设它们可以由 parent 提供并与之同步。只要 <video>
元素触发状态更改事件,这些属性就会在内部更新。
我最后还使用 $emit
方法将 <video>
元素的事件传播到组件的 parent。这样做是因为组件简单地引入了 HLS 并充当状态驱动程序。因此,它不完全响应并模仿普通的 <video>
元素是可以接受的。
控制面板成功引用了 更新 1 中所述的播放器组件。收到播放器的句柄后,很容易使用 $on
订阅它的事件,然后在状态更改事件时简单地点击它的计算属性。
最后,map 更容易实现,因为它遵循了所有其他 Vue 示例中描述的或多或少的简单流程。实际上,地图的 parent 跟踪当前时间。这个变量实际上是由控制面板使用 :currentTime.sync="currentTime"
属性更新的。但是,对于地图来说,感觉就好像parent自己在更新时间一样。
我正在探索 vue.js 并且对如何解决某个问题有疑问。
我的根组件具有以下模板:
<div class="container">
<div class="stage">
<map :current-time="currentTime" :recording="recording"></map>
<player :track="track" :current-time="currentTime"></player>
</div>
<control-panel :current-time="currentTime"></control-panel>
</div>
基本上,<player>
组件内部有 <video>
元素,它将加载指定的轨道(隐藏本机控件)。因此,它实际上会在视频播放时驱动应用程序的状态(当前时间、播放状态等)。但是,<control-panel>
具有指示视频状态的滑动条和按钮(play/pause,搜索)。显然,改变其中一个组件的一般状态会影响其他两个组件(地图也会根据当前时间进行处理)。
但是,我想知道这是否更有意义,以及 Vue 是否支持提供对组件的引用,以便我可以为 <control-panel>
提供对 <player>
的引用,以便它可以进行状态更改直接来自它。
或者应该以某种 global-state-passed-down-to-children 或 event-broadcast 的方式完成?在纠正我之前,请考虑一个示例,其中有两个 <player>
s 和两个 <control-panel>
s 在层次结构上不相关,但是一个 panelA 与 playerA 一起工作,而 panelB 与 playerB 一起工作。在这种情况下,我认为广播选项会掉落 table,对吗?
欢迎任何建议,尤其是在我刚刚学习 Vue 的时候。
更新 1
因此,在更加熟悉 Vue 并听取社区的反馈后,我想我想出了一个将 <player>
和 <control-panel>
同步在一起的聪明解决方案。我的标记更改为以下内容:
<div class="container">
<div class="stage">
<map :current-time="currentTime" :recording="recording"></map>
<player :track="track" :current-time="currentTime" v-ref:player></player>
</div>
<control-panel :current-time="currentTime" v-ref:player-controls :player="$refs.player"></control-panel>
</div>
注意 v-ref
属性添加到 <player>
和 <control-panel>
以及后者的 :player="$refs.player"
属性。这使我能够在逻辑上将一个与另一个联系在一起。在我看来,控制面板知道它在控制谁或什么是有意义的。我打算进一步测试它,但就目前而言,这似乎有效。
至于捆绑 <map>
,我将最终使用广播或简单地 two-way currentTime
由 <control-panel>
更新。我会随时更新此 post,如果与任何答案不同,我会标记正确答案或 post 我自己的答案。
更新 2
阅读下面我的回答。我已经能够使用以下方法成功解决我的问题。
我认为将它们作为独立的组件保留是个好主意;
然后您可以随时切换控制面板组件,使用另一个使用相同界面
(就像在电子商务应用程序中将 Stripe 换成其他支付处理器一样)
$broadcasting
和 $dispatching
即使有多个玩家在场也能正常工作,只要您为每个 broadcast/dispatch 传递一个标识符键,以便接收消息的每个组件可以立即确定如果是送给他们的。
解决方案涉及采用 更新 1 中描述的方法。因为 <video>
元素经过 API 的深思熟虑,将其转换为响应式组件相当容易(尽管很烦人)。
视频元素的包装器最终以下列方式创建了几个 computed
属性:
'currentTime': {
cache: false,
get: function () {
return this.$els.player.currentTime;
},
set: function (value) {
this.$els.player.currentTime = value;
}
}
属性 cache: false
必须使用,因为该属性未绑定到反应式元素,并且每次查询该属性时都需要重新计算。
不让组件完全反应是故意的。也就是说,我可以将需要的属性定义为 props
,并假设它们可以由 parent 提供并与之同步。只要 <video>
元素触发状态更改事件,这些属性就会在内部更新。
我最后还使用 $emit
方法将 <video>
元素的事件传播到组件的 parent。这样做是因为组件简单地引入了 HLS 并充当状态驱动程序。因此,它不完全响应并模仿普通的 <video>
元素是可以接受的。
控制面板成功引用了 更新 1 中所述的播放器组件。收到播放器的句柄后,很容易使用 $on
订阅它的事件,然后在状态更改事件时简单地点击它的计算属性。
最后,map 更容易实现,因为它遵循了所有其他 Vue 示例中描述的或多或少的简单流程。实际上,地图的 parent 跟踪当前时间。这个变量实际上是由控制面板使用 :currentTime.sync="currentTime"
属性更新的。但是,对于地图来说,感觉就好像parent自己在更新时间一样。