淺談vue實(shí)現(xiàn)數(shù)據(jù)監(jiān)聽的函數(shù) Object.defineProperty
在 ES5中新增了不少新的API, 例如 新增了 Object.xxx相關(guān)的方法,其中有一個(gè)定義屬性相關(guān)的 Object.defineProperty 這個(gè)方法(還有Object.defineProperties)這個(gè)方法是 vue框架實(shí)現(xiàn)數(shù)據(jù)監(jiān)聽的核心方法,它的定義如下:
Object.defineProperty([Object] obj, [String] propname, [Object] desp )
- @param obj 要配置屬性的某個(gè)對(duì)象
- @param propname 要配置的屬性名,是一個(gè)字符串
- @param desp 對(duì)屬性的描述,是一個(gè)對(duì)象,
desp 中可以配置的項(xiàng)目
<1> writable: true/false 是否可寫
<2> configurable : true/false 是否可以配置,例如刪除該屬性
<3> enumerable: true/false 指的是是否可以使用 for in循環(huán)遍歷屬性
<4> value: 值 ,屬性的值
我們?cè)趯憊ue項(xiàng)目的時(shí)候會(huì)在 data屬性中添加我們自己的屬性,這個(gè)屬性在vue中是響應(yīng)式的,也就是它可以監(jiān)聽到數(shù)據(jù)的變化,做出相應(yīng)的改變(例如DOM操作)
我們自己利用 defineProperty給屬性生成setter和getter(也就是其他編程語言里的存取器),就可以達(dá)到監(jiān)聽數(shù)據(jù)變化的目的
下面我們來自己實(shí)現(xiàn)一個(gè)數(shù)據(jù)監(jiān)聽的小 demo
有如下的數(shù)據(jù)
let vue = { data: { title: 'life style', content: 'bike walk sleep...' } };
已經(jīng)提前聲明的 data屬性及其內(nèi)部的屬性,我們的目標(biāo)是監(jiān)聽 data中,title和content的變化
如何做到呢? 屬性的個(gè)數(shù)是不確定的,所以我們可以使用 for in循環(huán)遍歷data對(duì)象的所有的屬性
//如何監(jiān)聽用戶自定義的 data中屬性的改變? let data = vue.data; for (let prop in data) { data['__' + prop] = data[prop]; //存儲(chǔ)私有屬性 Object.defineProperty(data, prop, { enumerable : true, set: function (newVal) { console.log('你正在修改'+prop + ' !...操作DOM...'); // 數(shù)據(jù)校驗(yàn) this['__' + prop] = newVal; }, get: function () { console.log('getter 獲取值 ...'); return this['__' + prop]; } }); }
遍歷data屬性的時(shí)候調(diào)用 defineProperty來給data對(duì)象的屬性添加set和get方法,
我們給data添加一個(gè)新的屬性 __xxx來保存我們之前的值,以便在 get方法中獲取原來的值
set方法 用于監(jiān)聽這個(gè)屬性被重新賦值,
get方法用于獲取你想要的格式的值
此處需要注意的是 不要在 set和get中 使用this賦值或者取值,這樣會(huì)導(dǎo)致循環(huán)調(diào)用,出現(xiàn)問題!!!
另外 我們不要使用 var,而要使用 let ,因?yàn)関ar不是塊作用域, 會(huì)導(dǎo)致你最后訪問到的prop總是最后一個(gè)
定義好之后,我們可以修改 data中title和content屬性了,
當(dāng)我們給 title賦值的時(shí)候回自動(dòng)調(diào)用 set, 獲取值得時(shí)候自動(dòng)調(diào)用get
測試代碼
// 賦值操作會(huì)調(diào)用這個(gè)屬性的set方法, 類似于 set('aaa') data.title = 'aaa'; // 獲取值操作會(huì)調(diào)用這個(gè)屬性的get方法 console.log(data.title); data.content = 123; // 此種動(dòng)態(tài)屬性方式也會(huì)觸發(fā) set / get data['title'] = 123; console.log(data['title']);
結(jié)果(建議在最新版的chrome中操作):
對(duì)剛剛的遍歷方法還存在一些問題和說明:
1.data屬性的某個(gè)屬性可能還是對(duì)象,也就是存在多層級(jí)對(duì)象監(jiān)聽的問題
此時(shí)可以使用遞歸函數(shù)遍歷data的屬性,進(jìn)行相同操作
2. 通過 data.title = 1是實(shí)際上是調(diào)用了 set方法, 這個(gè)類似于 OC中的點(diǎn)語法
3. 要同時(shí)定義多個(gè)屬性,可以使用
Object.defineProperties([Object] obj, [Object] props);
需要注意的是, 本文只是介紹 defineProperty的基本使用,并非代表vue的代碼實(shí)現(xiàn)
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Vue 組件修改根實(shí)例的數(shù)據(jù)的方法
這篇文章主要介紹了Vue 組件修改根實(shí)例的數(shù)據(jù)的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04mpvue性能優(yōu)化實(shí)戰(zhàn)技巧(小結(jié))
這篇文章主要介紹了mpvue性能優(yōu)化實(shí)戰(zhàn)技巧(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04在 Typescript 中使用可被復(fù)用的 Vue Mixin功能
這篇文章主要介紹了在 Typescript 中使用可被復(fù)用的 Vue Mixin功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-04-04Vue使用pdf-lib實(shí)現(xiàn)為文件流添加水印并預(yù)覽
這篇文章主要為大家詳細(xì)介紹了Vue如何使用pdf-lib實(shí)現(xiàn)為文件流添加水印并預(yù)覽的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-03-03優(yōu)雅的將ElementUI表格變身成樹形表格的方法步驟
這篇文章主要介紹了優(yōu)雅的將ElementUI表格變身成樹形表格的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04