簡體   English   中英

Vue3:創建的鈎子與數據字段中的對象實例化

[英]Vue3: Object instantiation in created hook vs data field

我正在將一個項目從 Vue2 遷移到 3,並試圖了解在組件數據上創建字段時遇到的錯誤。 使用 ToneJS,我可以在方法的主體中或在 created 鈎子中創建一個new Synth() ,並在我的playNote方法中調用它。 但是,當將合成器定義為data字段時,單擊“播放”按鈕時出現以下錯誤。

在 Vue2 中我沒有這樣的問題。 想知道是否有人可以解釋這里發生了什么? 為什么創建的鈎子有效,但數據字段無效?

感謝您對此的任何幫助! 錯誤的全文:

runtime-core.esm-bundler.js?5c40:6568 [Vue 警告]:在 <Main onVnodeUnmounted=fn ref=Ref< Proxy {playNote: ƒ, …} >> at warn @ 處執行本機事件處理程序期間未處理的錯誤runtime-core.esm-bundler.js?5c40:6568 logError @ runtime-core.esm-bundler.js?5c40:6742 handleError @ runtime-core.esm-bundler.js?5c40:6734 eval @ runtime-core.esm -bundler.js?5c40:6697 Promise.catch (async) callWithAsyncErrorHandling @ runtime-core.esm-bundler.js?5c40:6696 invoker @ runtime-dom.esm-bundler.js?830f:347 localhost/:1 Uncaught (承諾)DOMException

<template>    
<div>      
<button v-on:click="playNote">Play</button>    
</div>  
</template>   
<script lang="ts">  
import { defineComponent } from "vue";      
import * as Tone from 'tone'  

export default defineComponent({          
  name: "Main",          
  data() {              
    return {  
      synth: new Tone.Synth().toDestination(), // this throws an error 
      playing: false, 
    }
  },          
  methods: {              
    async playNote(){  
      console.log('playNote'); // logs properly await Tone.start();          
      console.log('this.synth', this.synth); // synth object logs        
      this.synth.triggerAttackRelease('C4', '8n');                   
    
      // this works:            
      // const synth = new Tone.Synth().toDestination();        
      // synth.triggerAttackRelease('C4', '8n');              
    },          
  },   
  created() {     
    // this.synth = new Tone.Synth().toDestination() // this also works   
  }    
});      
</script>

在 Vue 3 中,Vue 使用Proxy來跟蹤來自對象的更改(Vue 2 使用Object.defineProperty )。

當我們從組件的 data 函數返回一個普通的 JavaScript 對象時,Vue 會將該對象包裝在帶有 get 和 set 處理程序的代理中。

Vue 如何跟蹤這些變化

調試后,我發現錯誤來自standardized-audio-context包中名為get-native-context的文件,如果找不到某些上下文變量,則會拋出錯誤:

export const createGetNativeContext = (contextStore) => {
    return (context) => {
        const nativeContext = contextStore.get(context); // contextStore is a WeakMap
        if (nativeContext === undefined) {
            throw createInvalidStateError();
        }
        return (nativeContext);
    };
};

原始文件在這里

所以我的猜測是在庫中的某個地方存儲 Synth 上下文對象( synth.context._context )以備后用。 但是 Synth 上下文對象已經改為了 Proxy。 當它嘗試通過contextStore.get(context)獲取contextStore.get(context) ,它將返回undefined

從您的代碼:

created() {     
    this.synth = new Tone.Synth().toDestination()
}

這是因為this.synth只是一個沒有反應性的普通對象(代理)。

如果您不需要synth對象是反應式的,那么您的代碼在方法和創建的鈎子中都很好。 但是,如果您希望它具有反應性,則必須以某種方式包裝它。

例如:

...
  data() {
    return {
      synth: () => new Tone.Synth().toDestination()
    }
  },
  methods: {
    async playNote() {
      this.synth().triggerAttackRelease('C4', '8n')
    }
  }
...

這不是一個很好的例子,因為synth每次使用時都會創建。 JSFiddle

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM