[英]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 處理程序的代理中。
調試后,我發現錯誤來自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.