日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > vue >内容正文

vue

vue源码-对于「计算属性」的理解

發(fā)布時(shí)間:2025/3/21 vue 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 vue源码-对于「计算属性」的理解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

vue源碼-對(duì)于「計(jì)算屬性」的理解

這是我最近學(xué)習(xí)vue源碼的一個(gè)個(gè)人總結(jié)和理解,所以可能并不適合每一位讀者

本文的整體脈絡(luò)如下,首先盡可能去掉細(xì)節(jié),對(duì)計(jì)算屬性源碼的大致實(shí)現(xiàn)有一個(gè)了解,然后舉一例子,分別談?wù)動(dòng)?jì)算屬性依賴收集和派發(fā)更新的流程。

  • 計(jì)算屬性的源碼實(shí)現(xiàn)
  • 舉例來(lái)說(shuō),談?wù)勴?yè)面初次渲染時(shí),整個(gè)依賴收集的過(guò)程
  • 舉例來(lái)說(shuō),計(jì)算屬性的依賴被修改時(shí),派發(fā)更新的過(guò)程

另外推薦2個(gè)開(kāi)源的vue源碼分析集合

  • https://ustbhuangyi.github.io...
  • http://hcysun.me/vue-design/a...

計(jì)算屬性的源碼實(shí)現(xiàn)

  • _init() --> initState() --> initComputed()
  • 1.遍歷computed選項(xiàng),2.實(shí)例化computed watcher 3.defineComputed()
  • defineComputed()核心就是把計(jì)算屬性用Object.defineProperty包裝成響應(yīng)式對(duì)象,而getter就是把用戶傳入的函數(shù)作為getter
  • 但是準(zhǔn)確的說(shuō),是用戶傳遞的fn的返回值是作為計(jì)算屬性getter的return值,但是除此之外計(jì)算屬性在getter時(shí)還做了一些其他的操作
  • 1是watch.depend() 2.return watch.evaluate()。 也就是1.收集依賴2.把值返回
this._init() : 重點(diǎn)關(guān)注重點(diǎn)init方法中initState initLifecycle(vm)initEvents(vm)initRender(vm)callHook(vm, 'beforeCreate')initInjections(vm) // resolve injections before data/propsinitState(vm)initProvide(vm) // resolve provide after data/propscallHook(vm, 'created') initState() 重點(diǎn)關(guān)注這一句 if (opts.computed) initComputed(vm, opts.computed) export function initState (vm: Component) {vm._watchers = []const opts = vm.$optionsif (opts.props) initProps(vm, opts.props)if (opts.methods) initMethods(vm, opts.methods)if (opts.data) {initData(vm)} else {observe(vm._data = {}, true /* asRootData */)}if (opts.computed) initComputed(vm, opts.computed)if (opts.watch && opts.watch !== nativeWatch) {initWatch(vm, opts.watch)} } initComputed() 核心就是遍歷computed,每次循環(huán)都實(shí)例化一個(gè)computed watch,并且用defineComputed把計(jì)算屬性包裝成響應(yīng)式對(duì)象 function initComputed (vm: Component, computed: Object) {// $flow-disable-lineconst watchers = vm._computedWatchers = Object.create(null)// computed properties are just getters during SSRconst isSSR = isServerRendering()for (const key in computed) {const userDef = computed[key]const getter = typeof userDef === 'function' ? userDef : userDef.getif (process.env.NODE_ENV !== 'production' && 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 (process.env.NODE_ENV !== 'production') {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)}}} } defineComputed() 核心就是Object.defineProperty ,大段代碼都是在給它設(shè)置get和set export function defineComputed (target: any,key: string,userDef: Object | Function ) {const shouldCache = !isServerRendering()if (typeof userDef === 'function') {sharedPropertyDefinition.get = shouldCache? createComputedGetter(key): userDefsharedPropertyDefinition.set = noop} else {sharedPropertyDefinition.get = userDef.get? shouldCache && userDef.cache !== false? createComputedGetter(key): userDef.get: noopsharedPropertyDefinition.set = userDef.set? userDef.set: noop}if (process.env.NODE_ENV !== 'production' &&sharedPropertyDefinition.set === noop) {sharedPropertyDefinition.set = function () {warn(`Computed property "${key}" was assigned to but it has no setter.`,this)}}Object.defineProperty(target, key, sharedPropertyDefinition) } createComputedGetter : 計(jì)算屬性的getter就是這個(gè)computedGetter,做了2件事情,1.收集render watcher作為自己的依賴,2.調(diào)用用戶的那個(gè)函數(shù)作為返回值 function createComputedGetter (key) {return function computedGetter () {const watcher = this._computedWatchers && this._computedWatchers[key]if (watcher) {watcher.depend()return watcher.evaluate()}} }

到目前為止就結(jié)束了,也就是說(shuō)初始化computed watcher都沒(méi)有求值

直到render時(shí),才會(huì)觸發(fā)computed watcher的getter

舉例來(lái)說(shuō),談?wù)勴?yè)面初次渲染時(shí),整個(gè)依賴收集的過(guò)程

比如我們有一個(gè)計(jì)算屬性,并且fullName是渲染在模板中的。

computed: {fullName(){return this.firstName + this.lastName} }

那么頁(yè)面初次渲染時(shí),整個(gè)依賴收集的過(guò)程如下

  • render函數(shù)執(zhí)行時(shí),會(huì)讀取計(jì)算屬性fullName,那么會(huì)觸發(fā)fullName的getter,那么就會(huì)執(zhí)行到watch.depend()和return watch.evaluate()
  • 這個(gè)computed watcher的depend()會(huì)把render watcher作為依賴收集到它的subs里。
  • 這個(gè)computed watcher的evaluate()主要是把調(diào)用了用戶給的那個(gè)函數(shù),求值并返回
  • 最后值得注意的是,調(diào)用用戶的函數(shù),也就是執(zhí)行了this.firstName + this.lastName ,那么也會(huì)觸發(fā)他們的getter,所以他們也會(huì)把computed watcher作為依賴,收集到subs里,將來(lái)如果被修改的話,用通知subs里的watch調(diào)用update,也就是去派發(fā)更新

舉例來(lái)說(shuō),計(jì)算屬性的依賴被修改時(shí),派發(fā)更新的過(guò)程

  • 當(dāng)this.firstName或者this.lastName被修改時(shí),會(huì)觸發(fā)他們的setter,setter就干兩個(gè)事情。1是賦值 2是派發(fā)更新
  • 所以會(huì)通知他們的subs里的watch去調(diào)用自己的update方法。其中也包括computed watcher,
  • 那么computed watcher在update方法跟普通的user watcher的update存在區(qū)別,computed watcher并不是直接推入異步更新隊(duì)列,而是 this.dep.notify()發(fā)出之前計(jì)算屬性所收集的依賴去派發(fā)更新,其中就包括render watcher,調(diào)用render watcher的update就會(huì)實(shí)現(xiàn)視圖更新了
  • 注意this.getAndInvoke的作用,就是如果this.lastName和this.firstName變化了,但是經(jīng)過(guò)計(jì)算之后,計(jì)算屬性的值不變,那么也不會(huì)觸發(fā)notify的,也就不會(huì)更新視圖
update () {if (this.computed) {if (this.dep.subs.length === 0) {this.dirty = true} else {this.getAndInvoke(() => {this.dep.notify()})}} else if (this.sync) {this.run()} else {queueWatcher(this)} }

這也是為什么,我們說(shuō)計(jì)算屬性的依賴屬性不被修改的話,計(jì)算屬性就不會(huì)變化。因?yàn)間etter就是你那個(gè)函數(shù)嘛,而且其實(shí)就算依賴變化了,只要計(jì)算之后的計(jì)算屬性變,也不會(huì)觸發(fā)視圖更新。

總結(jié)

以上是生活随笔為你收集整理的vue源码-对于「计算属性」的理解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久五月天综合 | 就要操av | 日韩精品一区二区三区视频在线观看 | 蜜臀av免费在线观看 | 日本少妇一级片 | 反差在线观看免费版全集完整版 | 亚洲av无码成人精品区 | 日韩午夜视频在线观看 | 2020国产精品 | 少妇在军营h文高辣 | 国产熟女精品视频 | 毛片一级片 | 欧美成人午夜77777 | 日本黄色大片视频 | 国产精品一区二区三区四 | 欧美黑人啪啪 | xxxxxx日本 | 久久这里只有精品23 | 日本特黄视频 | 综合久色| 欧av在线 | 爽爽窝窝午夜精品一区二区 | 亚洲情侣av| 在线看国产视频 | 国产精品久久久久久久久久久久久 | 国产免费一区二区三区在线观看 | 一级全黄裸体免费观看视频 | www.国产麻豆| 亚洲第一视频网 | 久久99精品国产.久久久久久 | www.白虎 | 久久久久久久久蜜桃 | 欧美黑人一级爽快片淫片高清 | 在线看成人片 | 69精品在线观看 | 精品乱子一区二区三区 | 在线中文字幕一区 | 99热在线只有精品 | 成人深夜福利 | 国内福利视频 | 他趴在我两腿中间添得好爽在线看 | 国产精品一色哟哟哟 | 亚洲视频在线一区二区 | 老色批永久免费网站www | 污视频网站免费 | 国产一区二区三区视频播放 | 五月天久久综合 | 国产乱码一区二区 | 视频久久精品 | 久久爱影视i| 九九视频免费在线观看 | 日本一区二区三区视频在线 | 99热精品在线播放 | 国产白嫩美女无套久久 | 日韩性猛交ⅹxxx乱大交 | 91丨porny丨中文 | 中文字幕在线观看av | 人妻色综合网站 | 久久精品视频日本 | 91精品国产一区二区三竹菊影视 | 波多野结衣一区二区三区中文字幕 | 一区二区三区黄 | 亚洲欧美日韩在线看 | 日韩精品无码一区二区三区 | 久久精品一二区 | 不卡黄色 | 北条麻妃一区二区三区 | 中文字幕av一区二区 | 成人激情视频在线观看 | 免费成人蒂法网站 | 亚洲一区二区三区高清在线 | 中文字幕国产剧情 | 少妇av在线 | 丝袜诱惑一区 | 国产午夜精品无码一区二区 | 久久久久久久久91 | 午夜一级黄色片 | 一区二区三区午夜 | 亚洲先锋影音 | 911成人网 | 精品3p| 91在线免费观看网站 | 亚洲久热 | 波多野结衣亚洲一区 | 一级视频免费观看 | 九九午夜视频 | 乱妇乱女熟妇熟女网站 | 伊人网欧美 | 伊人久久97 | 丰满雪白极品少妇流白浆 | 91久久精品www人人做人人爽 | 97青草| 国产免费av电影 | 亚洲AV无码精品久久一区二区 | 性高潮久久久久久久 | 激情欧美日韩 | 午夜私人福利 | 国产十区 | 久草最新网址 |