vue數據驅動:data中的數據是如何通過this訪問到的呢
阿新 • • 發佈:2019-02-22
func htm prop 方式 ces guide root sha 為什麽
//html <div id="app"> {{message}} </div> //script new Vue({ el:"#app", router, template:"<App/>", data(){ return { message } },
mounted(){
console.log(this.message)//問題:為什麽可以通過this.message這種方式來訪問data中的數據呢
} })
在vue源碼中,可以發現數據data是定義在初始化對象$options中的,要想訪問到data中的key字段,正常來說是通過vm.$options.data.key來訪問的。那麽,在vue中是怎麽實現利用vm.key就能訪問到key字段呢。在源碼中,有一個方法為initData(),方法所在為:initMixin() -> _init() -> initState() ->initData(),具體如下:
function initData (vm) { var data = vm.$options.data; data = vm._data = typeof data === ‘function‘ ? getData(data, vm) : data || {};//將vm.$options.data存儲在變量data中,同時vm新建私有屬性_data映射該對象,這樣就可以通過vm._data訪問到data數據 if (!isPlainObject(data)) { data = {}; process.env.NODE_ENV !== ‘production‘ && warn( ‘data functions should return an object:\n‘ + ‘https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function‘, vm ); } // proxy data on instance var keys = Object.keys(data); var props = vm.$options.props; var methods = vm.$options.methods; var i = keys.length; while (i--) { var key = keys[i]; if (process.env.NODE_ENV !== ‘production‘) { if (methods && hasOwn(methods, key)) {//處理data中字段與methods方法字段命名沖突的情況 warn( ("Method \"" + key + "\" has already been defined as a data property."), vm ); } } if (props && hasOwn(props, key)) {//處理data中字段與props字段命名沖突的情況 process.env.NODE_ENV !== ‘production‘ && warn( "The data property \"" + key + "\" is already declared as a prop. " + "Use prop default value instead.", vm ); } else if (!isReserved(key)) { proxy(vm, "_data", key);//代理,實現vm.key直接訪問的關鍵方法。 } } // observe data observe(data, true /* asRootData */);//對數據添加觀察 }
在initData方法中,主要做的工作有:
- 將vm.$options.data映射到vm._data中,使得可以通過vm._data訪問數據變量
- 處理data與props、methods之間的變量命名沖突的情況
- 通道代理方法proxy來實現vm直接訪問data中的數據變量
proxy方法解讀為:
var sharedPropertyDefinition = { enumerable: true, configurable: true, get: noop, set: noop };//設置通用數據屬性變量。此變量就是對vm._data(也就是vm.$options.data)的代理 function proxy (target, sourceKey, key) { sharedPropertyDefinition.get = function proxyGetter () { return this[sourceKey][key] };/對屬性變量添加get方法。在讀取此屬性的時候,實際上讀取的是vm._data,也就是此變量就是對vm._data(也就是vm.$options.data)的代理
sharedPropertyDefinition.set = function proxySetter (val) {
this[sourceKey][key] = val;
}; //添加set方法
Object.defineProperty(target, key, sharedPropertyDefinition); //通過Object.defineProperty方法,將key直接掛在vm下,並且通過sharePropertyDefinition屬性的get和set方式,將對
vm._data的讀取讀和寫操作映射到了vm.key,到此,便實現了vm.key直接操作數據的代理。
}
vue數據驅動:data中的數據是如何通過this訪問到的呢