數據初始化
Vue 實例在建立的時候會運行一系列的初始化操作,而在這些初始化操作里面,和數據綁定關聯最大的是 initState。
首先,來看一下他的代碼:
function initState(vm) { vm._watchers = []; var opts = vm.$options; if(opts.props) { initProps(vm, opts.props); //初始化props } if(opts.methods) { initMethods(vm, opts.methods); //初始化methods } if(opts.data) { initData(vm); //初始化data } else { observe(vm._data = {}, true /* asRootData */ ); } if(opts.computed) { initComputed(vm, opts.computed); //初始化computed } if(opts.watch && opts.watch !== nativeWatch) { initWatch(vm, opts.watch); //初始化watch }}在這么多的數據的初始化中,props、methods和data是比較簡單的(所以我就不詳細介紹了☺),而computed 和 watch則相對較難,邏輯較復雜,所以我下面主要講下computed 和 watch(以下代碼部分為簡化后的)。
initState里面主要是對vue實例中的 props, methods, data, computed 和 watch 數據進行初始化。
在初始化props的時候(initProps),會遍歷props中的每個屬性,然后進行類型驗證,數據監測等(提供為props屬性賦值就拋出警告的鉤子函數)。
在初始化methods的時候(initMethods),主要是監測methods中的方法名是否合法。
在初始化data的時候(initData),會運行 observe 函數深度遍歷數據中的每一個屬性,進行數據劫持。
在初始化computed的時候(initComputed),會監測數據是否已經存在data或props上,如果存在則拋出警告,否則調用defineComputed函數,監聽數據,為組件中的屬性綁定getter及setter。如果computed中屬性的值是一個函數,則默認為屬性的getter函數。此外屬性的值還可以是一個對象,他只有三個有效字段set、get和cache,分別表示屬性的setter、getter和是否啟用緩存,其中get是必須的,cache默認為true。
function initComputed(vm, computed) { var watchers = vm._computedWatchers = Object.create(null); for(var key in computed) { var userDef = computed[key]; var getter = typeof userDef === 'function' ? userDef : userDef.get; //創建一個計算屬性 watcher watchers[key] = new Watcher( vm, getter || noop, noop, computedWatcherOptions ); if(!(key in vm)) { //如果定義的計算屬性不在組件實例上,對屬性進行數據劫持 //defineComputed 很重要,下面我們再說 defineComputed(vm, key, userDef); } else { //如果定義的計算屬性在data和props有,拋出警告 } }}在初始化watch的時候(initWatch),會調用vm.$watch函數為watch中的屬性綁定setter回調(如果組件中沒有該屬性則不能成功監聽,屬性必須存在于props、data或computed中)。如果watch中屬性的值是一個函數,則默認為屬性的setter回調函數,如果屬性的值是一個數組,則遍歷數組中的內容,分別為屬性綁定回調,此外屬性的值還可以是一個對象,此時,對象中的handler字段代表setter回調函數,immediate代表是否立即先去執行里面的handler方法,deep代表是否深度監聽。
新聞熱點
疑難解答
圖片精選