【问题标题】:VueJS connect unrelated (as in parent/child) componentsVueJS 连接不相关的(如父/子)组件
【发布时间】:2016-02-23 13:57:47
【问题描述】:

我正在探索 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>

基本上,&lt;player&gt; 组件内部有&lt;video&gt; 元素,它将加载指定的轨道(隐藏本机控件)。因此,它实际上会在视频播放时驱动应用程序的状态(当前时间、播放状态等)。但是,&lt;control-panel&gt; 有一个滑动条和指示视频状态(播放/暂停、搜索)的按钮。显然,改变其中一个组件的这种一般状态会影响其他两个组件(地图也会根据当前时间进行)。

但是,我想知道这是否更有意义,以及 Vue 是否支持提供对组件的引用,以便我可以向 &lt;control-panel&gt; 提供对 &lt;player&gt; 的引用,以便它可以直接从中获取状态更改。

或者这应该以一种全局状态传递给孩子或事件广播的方式来完成?在我更正之前,请考虑一个示例,其中有两个&lt;player&gt;s 和两个&lt;control-panel&gt;s 在层次上不相关,但一个 panelA 与 playerA 一起使用,而 panelB 与 playerB 一起使用。在这种情况下,我认为广播选项不合适了,对吗?

欢迎任何建议,特别是因为我刚刚学习 Vue。

更新 1

因此,在对 Vue 更加熟悉并听取了社区的反馈后,我想我想出了一个巧妙的解决方案,将 &lt;player&gt;&lt;control-panel&gt; 同步在一起。我的标记更改为:

<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 属性添加到&lt;player&gt;&lt;control-panel&gt; 以及后者中的:player="$refs.player" 属性。这使我能够在逻辑上将彼此联系在一起。在我看来,控制面板知道它在控制谁或控制什么是有意义的。我将进一步测试它,但目前看来,这似乎可行。

至于捆绑&lt;map&gt;,我最终将使用广播或简单的双向currentTime &lt;control-panel&gt; 更新。我会随时更新这篇文章,如果与任何答案不同,我会标记正确答案或发布我自己的答案。

更新 2

在下面阅读我的答案。我已经能够使用以下方法成功解决我的问题。

【问题讨论】:

  • $broadcasting$dispatching 仍然可以通过 props 将 id 传递给组件来与多个玩家一起工作
  • 这种方法的问题是播放器和控件需要 id 才能运行。但是,它们是潜在的独立组件。如果我以这种方式实现它们,那么生成一个播放器组件将需要父级为其提供一个 id(因为必须向他们俩都提供该 id,以便他们知道要过滤掉哪些消息)。这通常是所有 MVVM 框架的问题吗?我的意思是,我喜欢我可以做这种动态绑定之类的东西,但有时,我需要完全手动控制,而且将 Vue 或 React 与普通 JS 混合似乎并不那么直接。

标签: javascript mvvm vue.js


【解决方案1】:

我认为将它们作为独立组件保留是个好主意;

然后,您可以随时将控制面板组件切换到另一个使用相同界面

的组件

(就像在电子商务应用程序中将 Stripe 与其他支付处理器一起切换)

$broadcasting$dispatching 工作良好,即使有多个玩家在场,只要您在每次广播/调度中传递一个标识符键,以便接收消息的每个组件都可以立即确定它是否是为他们发送的。

【讨论】:

  • 我还在解决这个问题。我最终可能会使用$broadcasting 进行map-video 时间同步,但我想我想出了一个聪明的方法来同步videocontrols。我正在通过更改更新我的问题。
【解决方案2】:

解决方案涉及采用更新 1 中描述的方法。因为&lt;video&gt; 元素有一个经过深思熟虑的 API,所以将其转换为反应式组件相当容易(虽然很烦人)。

视频元素的包装器最终以下列方式创建了多个computed 属性:

'currentTime': {
    cache: false,
    get: function () {
        return this.$els.player.currentTime;
    },
    set: function (value) {
        this.$els.player.currentTime = value;
    }
}

必须使用属性cache: false,因为该属性未绑定到反应性元素,并且每次查询该属性时都需要重新计算。

故意不让组件完全反应。也就是说,我可以将所需的属性定义为props,并假设它们可以由父级提供并与父级同步。只要&lt;video&gt; 元素触发状态更改事件,这些属性就会在内部更新。

我最后还使用$emit 方法将&lt;video&gt; 元素的事件传播到组件的父级。这样做是因为组件只是引入了 HLS 并充当状态驱动程序。因此,它不完全反应并模仿普通的&lt;video&gt; 元素是可以接受的。

控制面板成功引用了 Update 1 中声明的播放器组件。收到播放器的句柄后,很容易使用 $on 订阅其事件,然后在状态更改事件时简单地点击其计算属性。

最后,map 更容易实现,因为它遵循了所有其他 Vue 示例中描述的或多或少的简单流程。实际上,map 的父级会跟踪当前时间。这个变量实际上是由控制面板使用:currentTime.sync="currentTime" 属性更新的。但是,在地图上,感觉就像父级本身在更新时间一样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-31
    • 2019-10-31
    • 2021-07-30
    • 2023-02-25
    • 2018-09-08
    • 2017-08-18
    • 2017-03-17
    相关资源
    最近更新 更多