Vue核心之資料劫持

2022-09-09 23:42:26 字數 2451 閱讀 9974

當前前端界空前繁榮,各種框架橫空出世,包括各類mvvm框架橫行霸道,比如anglar,regular,vue,react等等,它們最大的優點就是可以實現資料繫結,再也不需要手動進行dom操作了,它們實現的原理也基本上是髒檢查或資料劫持。那麼本文就以vue框架出發,探索其中資料劫持的奧秘(本文所選取的相關**源自於vue v2.0.3版本的原始碼)。

首先我們應該搞清楚什麼是資料劫持,說白了就是通過object.defineproperty()來劫持物件屬性的setter和getter操作,在資料變動時做你想要做的事情,舉個栗子:

var data = 

object.keys(data).foreach(function(key),

set:function()

})});data.name //控制台會列印出 「get」

data.name = 'hxx' //控制台會列印出 "監聽到資料發生了變化"

上面的這個栗子可以看出,我們完全可以控制物件屬性的設定和讀取。在vue中,作者在很多地方都非常巧妙的運用了defineproperty這個方法,具體用在**並且它又解決了哪些問題,下面做詳細的介紹:

這個應該是vue非常重要的一塊,其主要思想是observer每個物件的屬性,新增到訂閱器dep中,當資料發生變化的時候發出notice通知。 相關源**如下:(作者採用的是es6+flow寫的,**在src/core/observer/index.js模組裡面)

export function definereactive (

obj: object,

key: string,

val: any,

customsetter?: function

) // cater for pre-defined getter/setters

const getter = property && property.get

const setter = property && property.set

let childob = observe(val)//建立乙個觀察者物件

object.defineproperty(obj, key,

if (array.isarray(value))

}return value

},set: function reactivesetter (newval)

if (process.env.node_env !== 'production' && customsetter)

if (setter) else

childob = observe(newval)//繼續監聽新的屬性值

dep.notify()//這個是真正劫持的目的,要對訂閱者發通知了}})

}

以上是監聽物件屬性的變化,那麼下面再看看如何監聽陣列的變化:

const arrayproto = array.prototype

export const arraymethods = object.create(arrayproto)

;[ 'push',

'pop',

'shift',

'unshift',

'splice',

'sort',

'reverse'

].foreach(function (method)

const ob = this.__ob__

let inserted

switch (method)

if (inserted) ob.observearray(inserted)

// notify change

ob.dep.notify()

return result

})})...

/** * define a property.

*/function def (obj, key, val, enumerable) );

}

通過上面的**可以看出vue是通過修改了陣列的幾個操作的原型來實現的。

正常情況下我們是這樣例項化乙個vue物件:

var vm = new vue(,

el:'#id'

})

function proxy (vm, key) ,

set: function proxysetter (val)

});}}

表面上看起來我們是在操作vm.name,實際上還是通過object.defineproperty()中的get和set方法劫持實現的。

vue框架很好的利用了object.defineproperty()這個方法來實現了資料的監聽和修改,同時也達到了很好的模組間解耦,在日常開發用好這個方法說不定會達到令人意想不到的結果。

Vue框架核心之資料劫持

引數obj 目標物件 prop 需要定義的屬性或方法的名稱 descriptor 目標屬性所擁有的特性 可供定義的特性列表 value 屬性的值 writable 如果為false,屬性的值就不能被重寫。get 一旦目標屬性被訪問就會調回此方法,並將此方法的運算結果返回使用者。set 一旦目標屬性被...

Vue框架核心之資料劫持

引數obj 目標物件 prop 需要定義的屬性或方法的名稱 descriptor 目標屬性所擁有的特性 可供定義的特性列表 value 屬性的值 writable 如果為false,屬性的值就不能被重寫。get 一旦目標屬性被訪問就會調回此方法,並將此方法的運算結果返回使用者。set 一旦目標屬性被...

vue 資料劫持

其實,並沒有這麼 神奇 的事,資料劫持的核心就是在 物件的身上重新定義被 物件所有可列舉屬性,並設定 getter 和 setter 監視著它的變化,然而實現這個核心功能就是乙個方法 object.defineproperty 通過該方法在例項物件上重新定義了和data物件裡面的所有屬性,然而就實現...