日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

前言:

前言就是有了前幾篇的基礎(chǔ)對(duì)于vue響應(yīng)式原理的初步了解之后,再去看這兩個(gè)東西會(huì)方便很多。寫(xiě)這篇文章是為了一個(gè)梳理,還有一些其他的原因,年底再說(shuō)。

 

先看computed

 

computed是在initState的時(shí)候,并且在初始化data之后,進(jìn)行初始化的,來(lái)看看初始化的時(shí)候它干了什么:

function initComputed (vm, computed) { // $flow-disable-line var watchers = vm._computedWatchers = Object.create(null); // computed properties are just getters during SSR var isSSR = isServerRendering(); for (var key in computed) { var userDef = computed[key]; var getter = typeof userDef === 'function' ? userDef : userDef.get; if (getter == null) { warn( ("Getter is missing for computed property "" + key + ""."), vm ); } if (!isSSR) { // create internal watcher for the computed property. watchers[key] = new Watcher( vm, getter || noop, noop, computedWatcherOptions ); } // component-defined computed properties are already defined on the // component prototype. We only need to define computed properties defined // at instantiation here. if (!(key in vm)) { defineComputed(vm, key, userDef); } else { if (key in vm.$data) { warn(("The computed property "" + key + "" is already defined in data."), vm); } else if (vm.$options.props && key in vm.$options.props) { warn(("The computed property "" + key + "" is already defined as a prop."), vm); } } } }

兩參數(shù)vm computed就是當(dāng)前的vm組件和實(shí)例上的computed屬性,說(shuō)得通俗點(diǎn)就是new Vue的時(shí)候?qū)懙哪莻€(gè)computed,然后我直接關(guān)注for in 里的代碼:這里拿到computed上的key和對(duì)應(yīng)的value之后,第一步是取得computed里key對(duì)應(yīng)的value,這里value可能會(huì)是一個(gè)函數(shù),一個(gè)對(duì)象,如果是函數(shù)就直接取,如果是對(duì)象就取他的get方法,然后會(huì)為當(dāng)前的key生成一個(gè)watcher:

watchers[key] = new Watcher( vm, getter || noop, noop, computedWatcherOptions ); //computedWatcherOptions 等于 var computedWatcherOptions = { lazy: true };

這里啊,這個(gè)lazy如果你對(duì)watcher構(gòu)造函數(shù)的源碼模糊了,建議重新打開(kāi)一個(gè)窗口看看,computed從源碼角度來(lái)講,為什么data里的值變了之后才會(huì)跟著變呢,是因?yàn)檫@個(gè)地方,

第二步是判斷當(dāng)前key是否與props或data里邊的key重復(fù),有則警告,沒(méi)有就調(diào)用defineComputed:

function defineComputed ( target, key, userDef ) { var shouldCache = !isServerRendering(); if (typeof userDef === 'function') { sharedPropertyDefinition.get = shouldCache ? createComputedGetter(key) : createGetterInvoker(userDef); sharedPropertyDefinition.set = noop; } else { sharedPropertyDefinition.get = userDef.get ? shouldCache && userDef.cache !== false ? createComputedGetter(key) : createGetterInvoker(userDef.get) : noop; sharedPropertyDefinition.set = userDef.set || noop; } if (sharedPropertyDefinition.set === noop) { sharedPropertyDefinition.set = function () { warn( ("Computed property "" + key + "" was assigned to but it has no setter."), this ); }; } Object.defineProperty(target, key, sharedPropertyDefinition); } //這里 var sharedPropertyDefinition = { enumerable: true, configurable: true, get: noop, set: noop };

直接看最后一句,vue的老套路了,劫持一個(gè)對(duì)象的屬性的get set,還有一層作用是執(zhí)行vm.key的時(shí)候把這個(gè)操作代理到了當(dāng)前定義的get上,其實(shí)computed的set不怎么常用,那來(lái)看看這里的get是什么:shouldChache是isServerRendering的執(zhí)行結(jié)果取反的結(jié)果,isServerRendering 字如其名自然跟服務(wù)端渲染相關(guān),看源碼的話,當(dāng)在服務(wù)端運(yùn)行的時(shí)候此值才有可能取真值,那這里他就是false,然后,shouldChache自然取true,接著走,然后computed對(duì)應(yīng)的value一般為function,所以這里執(zhí)行createComputedGetter:


function createComputedGetter (key) { return function computedGetter () { var watcher = this._computedWatchers && this._computedWatchers[key]; if (watcher) { if (watcher.dirty) { watcher.evaluate(); } if (Dep.target) { watcher.depend(); } return watcher.value } } }

這里實(shí)際是把key閉了一個(gè)包,返回的函數(shù)呢,就是sharedPropertyDefinition的get,所以,此后某個(gè)地方訪問(wèn)vm.key的時(shí)候這個(gè)閉包函數(shù)就會(huì)執(zhí)行,再看一下這個(gè)函數(shù)執(zhí)行的細(xì)節(jié),第一步取得當(dāng)前computed里key對(duì)應(yīng)的watcher實(shí)例,然后判斷watcher.dirty是否為true,這個(gè)dirty和上邊提到的lazy在實(shí)例化watcher的時(shí)候用的是同一個(gè)值,在初始化所有computed的時(shí)候他們都為true,因此第一次渲染的時(shí)候,這個(gè)地方會(huì)執(zhí)行到watcher.evaluate():

Watcher.prototype.evaluate = function evaluate () { this.value = this.get(); this.dirty = false; };

evaluate很簡(jiǎn)單,計(jì)算value,標(biāo)記dirty為false,這里的get前面我們也應(yīng)該講過(guò):他做了一件事情就是將當(dāng)前watcher pushTarget,然后調(diào)用watcher實(shí)例的getter方法,getter方法就是初始化watcher的時(shí)候傳進(jìn)去的那個(gè)getter,那這個(gè)getter里的東西呢,我們注意到computed里一般都會(huì)訪問(wèn)到當(dāng)前data的get方法,而前幾篇講了在get方法中,我們就能收集到當(dāng)前的watcher,因此此時(shí)就會(huì)完成依賴收集。然后computed就定義完畢了。

分享到:
標(biāo)簽:vue2
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定