關於vue中使用three.js報錯的解決方法
前言
最近在學習three.js,同時也學習一下vue3,然後就出現問題瞭,報錯直接用不瞭,錯誤信息如下:
Uncaught TypeError: 'get' on proxy: property 'modelViewMatrix' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '#' but got '[object Object]')
這個是什麼鬼???相信大傢都把錯誤信息復制到百度搜瞭一下解決方案吧?遇到問題的人並不多,解決方案就是把scene、mesh 啥的放到全局變量中,不放到data中,好的問題解決瞭。
我這樣寫是不是有點水文的嫌疑?作為一個成熟的程序員怎麼能水文呢?我得找到為什麼會出現這個問題才行,於是我花瞭兩個小時找到問題所在,也是怪自己不夠專業,不然應該花不瞭兩個小時。
1. vue的問題?
眾所周知,vue3是通過Proxy實現的數據雙向綁定,vue2是通過defindeProperty實現的數據雙向綁定,vue2的源碼我也看過,應該也是會有這個問題的,因為在開發模式下面,如果瀏覽器支持Proxy還是會用Proxy,我沒有用vue2去嘗試,大傢可以自行去嘗試,不出意外也會有這個問題。
上面說瞭一堆,就是為瞭引出Proxy的異常情況,好瞭又可以學習一下Proxy的知識瞭
2. Proxy的異常情況
在使用Proxy時,當屬性存在屬性特性configurable: false, value: undefined,
時,則取其屬性值時會報錯:
const handle = { get() { return 1; }, }; const obj = Object.create(null); Object.defineProperty(obj, 'a', { configurable: false, }); Object.defineProperty(obj, 'b', { value: undefined, }); Object.defineProperty(obj, 'c', { configurable: true, value: 'c', }); const proxy = new Proxy(obj, handle); console.log(proxy.a); // 報錯TypeError: 'get' on proxy: property 'a' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected 'undefined' but got '1') console.log(proxy.b); // 報錯Uncaught TypeError: 'get' on proxy: property 'b' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected 'undefined' but got '1') console.log(proxy.c); // 1
看看上面的報錯,是不是很熟悉?這樣看是不是一下就知道是什麼問題瞭?
3. Three.js 的問題
this.scene = new Scene(); this.scene.modelViewMatrix;
直接運行上面的代碼,就會看到文首出現的錯誤,錯誤原因就是因為configurable設置為false,找到問題就要解決問題,是不是覺得直接使用defineProperty就可以解決瞭?
很抱歉,這個不行,再來學習一下defineProperty。
4. defineProperty異常情況
MDN中是這樣描述的
如果屬性已經存在,
Object.defineProperty()
將嘗試根據描述符中的值以及對象當前的配置來修改這個屬性。如果舊描述符將其configurable 屬性設置為false,則該屬性被認為是“不可配置的”,並且沒有屬性可以被改變(除瞭單向改變 writable 為 false)。當屬性不可配置時,不能在數據和訪問器屬性類型之間切換。
當試圖改變不可配置屬性(除瞭 value 和 writable 屬性之外)的值時,會拋出TypeError,除非當前值和新值相同。
也就是說之前定義瞭configurable為false,就不能再將configurable改為true瞭,那怎麼辦?我說瞭問題當然是要給你解決的。
5. 解決
之前在網上查瞭,全局變量來處理,但是我使用的vue啊,我當然是希望將它定義到data中的,但是定義到data中就會自動生成代理,那就隻能從源碼入手瞭。 我也就不講我是怎麼去找源碼的,我直接上解決之後的吧,在node_modules\three\build\three.module.js
這個文件中,第7392行,裡面的代碼如下:
Object.defineProperties( this, { position: { configurable: true, enumerable: true, value: position }, rotation: { configurable: true, enumerable: true, value: rotation }, quaternion: { configurable: true, enumerable: true, value: quaternion }, scale: { configurable: true, enumerable: true, value: scale }, modelViewMatrix: { value: new Matrix4() }, normalMatrix: { value: new Matrix3() } } );
看到瞭吧,裡面有一個modelViewMatrix屬性,它沒有設置configurable屬性描述,也就是默認為false,加上就好瞭,改好瞭如下:
Object.defineProperties( this, { position: { configurable: true, enumerable: true, value: position }, rotation: { configurable: true, enumerable: true, value: rotation }, quaternion: { configurable: true, enumerable: true, value: quaternion }, scale: { configurable: true, enumerable: true, value: scale }, modelViewMatrix: { configurable: true, value: new Matrix4() }, normalMatrix: { value: new Matrix3() } } );
然後重啟服務,就不會報錯瞭,當然這種方式是有缺陷的,因為改瞭隻是你本地的,你其他同事的代碼並沒有改,如果要升級three.js也會把改瞭的代碼重新覆蓋,同時也不知道為什麼three.js要這樣處理這個變量,這個就看自己是怎麼處理的,我這次隻處理這個問題。
總結
到此這篇關於vue中使用three.js報錯解決的文章就介紹到這瞭,更多相關vue使用three.js報錯內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- JavaScript Object.defineProperty與proxy代理模式的使用詳細分析
- vue.js數據響應式原理解析
- 一文讀懂JavaScript 中的延遲加載屬性模式
- 淺析vue偵測數據的變化之基本實現
- javascript對象3個屬性特征