简体   繁体   English

将数据传递给 Vue 子组件而无需重新安装它

[英]Passing data to Vue child component without re-mounting it

I have a page that includes some audio visualization that's being done within a component.我有一个页面,其中包含在组件内完成的一些音频可视化。 The component is only for displaying stuff, the audio logic is done in the parent.该组件仅用于显示内容,音频逻辑在父级中完成。 I'll keep this part short, since my problem is more general, but basically I'm passing the AnalyserNode to the child to poll the realtime frequency analysis from within my Three.js render-loop in the child (WorkletModule).我将保持这部分简短,因为我的问题更普遍,但基本上我将 AnalyserNode 传递给孩子,以从我的 Three.js 渲染循环(WorkletModule)中轮询实时频率分析。

So in my parent I have something like this:所以在我的父母我有这样的事情:

<template>
    ...
    <WorkletModule
      :analyser="analyser"
      :key="componentKey"
    />
    ...
</template>

...

data() {
    return {
      componentKey: 0,
      analyser: null,
    };

methods: {
     startRecording() {
      this.componentKey++
      ..

      this.analyser = audioContext.createAnalyser();
      ..
     }
}

while my WorkletModule.vue looks like this:而我的WorkletModule.vue看起来像这样:

  props: {
    analyser: {
      type: AnalyserNode
    },
  },

  mounted() {
      //initialize graphics, etc..
  }

//in the render loop I need to do something like this:
this.analyser.getByteFrequencyData(soundData);

Now if I use it like above, it does actually work, however, every call to startRecording() causes the WorkletModule to re-mount, creating a hick-up and emptying the canvas of the WorkletModule.现在,如果我像上面一样使用它,它确实可以工作,但是,每次调用startRecording()都会导致 WorkletModule 重新挂载,创建一个连接并清空 WorkletModule 的画布。

If I remove the ":key="componentKey" it doesn't get updated, which means that the reference to the analyzer in the WorkletModule/prop always stays null, which is obviously not what I want. Is there a way to pass the analyzer object in another form than a prop?如果我删除":key="componentKey"它不会更新,这意味着 WorkletModule/prop 中对分析器的引用始终保持为 null,这显然不是我想要的。有没有办法通过分析器对象的另一种形式而不是道具?

Basically I need the analyzer value in every frame of the render-loop.基本上我需要渲染循环的每一帧中的分析器值。 I could not pass it as a prop but rather emit an event from the render loop of the WorkletModule that in turn gets the parent to send the current values back to the child via another event.我无法将它作为道具传递,而是从 WorkletModule 的渲染循环发出一个事件,该事件反过来让父级通过另一个事件将当前值发送回子级。 That doesn't seem like a very elegant thing though, so I guess there's a better way.但这似乎不是一件非常优雅的事情,所以我想有更好的方法。

I'm really puzzled by this:我真的很困惑:

If I remove the ":key="componentKey" it doesn't get updated, which means that the reference to the analyser in the WorkletModule/prop always stays null如果我删除 ":key="componentKey" 它不会更新,这意味着WorkletModule/prop 中对分析器的引用始终保持为空

This is not supposed to happen since props are updated without re-rendering by default.这不应该发生,因为道具在默认情况下无需重新渲染即可更新。 Of course, if you use a key, the component is fully destroyed and recreated on every key update.当然,如果您使用密钥,则组件会在每次密钥更新时完全销毁并重新创建。

You could listen to your props update by using a watcher.您可以使用观察者收听道具更新。

In the example below, I pass a prop to a children component, from null to a number.在下面的示例中,我将一个 prop 传递给子组件,从 null 到一个数字。 The component is only rendered once and the prop is updated as expected.组件只渲染一次,prop 按预期更新。 I only added a watcher to track every update of the said prop and give me the possibility to add any logic from that.我只添加了一个观察者来跟踪所述道具的每次更新,并让我可以从中添加任何逻辑。 You could try to do that in order to understand if the prop is really never updated or maybe your implementation lacks something (and you didn't show us the malicious bit of code that drives you into thinking it's not updated).您可以尝试这样做以了解 prop 是否真的从未更新,或者您的实现是否缺少某些东西(并且您没有向我们展示让您认为它没有更新的恶意代码)。

 const test = Vue.component("test", { props: ["prop1"], methods: { getProp() { console.log(this.prop1); } }, created() { console.log("created"); // only called once setInterval(this.getProp, 2000); }, watch: { prop1(newVal, oldVal) { console.log("watcher:", newVal, oldVal); // do something } }, template: "<div>test</div>" }); new Vue({ el: "#app", components: { test }, data: { toProp: null }, methods: { setProp() { this.toProp = new Date().valueOf(); } }, created() { setInterval(this.setProp, 6000); } })
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <test :prop1="toProp" /> </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM