摘要:前言最近在學習計算屬性的源碼,發(fā)現(xiàn)和普通的響應式變量內部的實現(xiàn)還有一些不同,特地寫了這篇博客,記錄下自己學習的成果文中的源碼截圖只保留核心邏輯完整源碼地址可能需要了解一些響應式的原理版本計算屬性的概念一般的計算屬性值是一個函數(shù),這個函數(shù)
前言
最近在學習Vue計算屬性的源碼,發(fā)現(xiàn)和普通的響應式變量內部的實現(xiàn)還有一些不同,特地寫了這篇博客,記錄下自己學習的成果
文中的源碼截圖只保留核心邏輯 完整源碼地址
可能需要了解一些Vue響應式的原理
Vue 版本:2.5.21
計算屬性的概念一般的計算屬性值是一個函數(shù),這個函數(shù)會返回一個值,并且其函數(shù)內部還可能會依賴別的變量
一般的計算屬性看起來和 method 很像,值都是一個函數(shù),那他們有什么區(qū)別呢
計算屬性和method的區(qū)別將一個計算屬性的函數(shù)放在 methods 中同樣也能達到相同的效果
但是如果視圖中依賴了這個 method 的返回值,并且當另外一個其他的響應式變量的修改導致視圖被更新時, method 會重新執(zhí)行一遍,即使這次的更新和 method 中依賴的變量沒有任何關系!
而對于計算屬性,只有當計算屬性依賴的變量改變后,才會重新執(zhí)行一遍函數(shù),并重新返回一個新的值
點我看示例
當 otherProp 變量被修改導致更新視圖的時候,methodFullName 每次都會執(zhí)行,而 computedFullName 只會在頁面初始化的時候執(zhí)行一次,Vue 推薦開發(fā)者將 method 和 compute 屬性區(qū)分開來,能夠有效的提升性能,避免執(zhí)行一些不必要的代碼
回顧過計算屬性的概念,接下來我們深入源碼,來了解一下計算屬性到底是怎么實現(xiàn)的,為什么只有計算屬性的依賴項被改變了才會重新求值
從例子入手這里我寫了一個簡單的例子,幫助各位理解計算屬性的運行原理,下面的解析會圍繞這個例子進行解析
const App = {
template: `
{{fullName}}
`,
data() {
return {
firstName: "尤",
lastName: "雨溪",
}
},
methods: {
handleChangeName() {
this.lastName = "大大"
}
},
computed: {
fullName() {
return this.firstName + this.lastName
}
}
}
new Vue({
el: "#app",
components: {
App
},
template: `
`
}).$mount()
fullName 依賴了 firstName 和 lastName,點擊 button 會修改 lastName, 同時 fullName 會重新計算,視圖變成"尤大大"
深入計算屬性的源碼
在日常開發(fā)中書寫的計算屬性,實際上內部都會保存一個 watcher, watcher 的作用是觀察某個響應式變量的改變然后執(zhí)行相應的回調,由 Watcher 類實例化而成, Vue 中定義了3個 watcher
render watcher: 模板依賴并且需要顯示在視圖上變量,其內部保存了一個 render watcher
computed watcher: 計算屬性內部保存了一個 computed watcher
user watcher: 使用 watch 屬性觀察的變量內部保存了一個 user watcher
理解這3個 watcher 各自的作用非常重要,文本會著重圍繞 computed watcher 展開
一個計算屬性的初始化分為2部分
實例化一個 computed watcher
定義計算屬性的 getter 函數(shù)
在初始化當前組件時,會執(zhí)行 initComputed 方法初始化計算屬性,會給每個計算屬性實例化一個 computed watcher
在實例化 watcher 時傳入不同的配置項就可以生成不同的 watcher 實例 ,當傳入{ lazy: true } 時,實例化的 watcher 即為 computed watcher
定義計算屬性的 getter 函數(shù)在創(chuàng)建完 computed watcher 后,接著會定義計算屬性的 getter 函數(shù),我們在執(zhí)行計算屬性的函數(shù)時,實際上執(zhí)行的是 computedGetter 這個函數(shù)
computedGetter代碼很少,但是卻是計算屬性的核心,我們一步步來分析
dirty屬性通過 key 獲取到第一步中定義的 computed watcher,隨后會判斷這個 computed watcher 的 dirty 屬性是否為 true,當 dirty 為 true 時, 會執(zhí)行 evaluate 方法, evaluate 內部會執(zhí)行計算屬性的函數(shù),并且將 watcher 的 value 屬性等于函數(shù)執(zhí)行后的結果也就是最終計算出來的值,具體我們放到后面講
dirty 屬性是一個用來檢測當前的 computed watcher是否需要重新執(zhí)行的一個標志,這也是計算屬性和普通method的區(qū)別,結合上圖可以發(fā)現(xiàn),當 dirty 為 false 時,就不會去執(zhí)行 evaluate 也就不會執(zhí)行計算屬性的函數(shù),可以看到最后直接就返回了 watcher.value 表示這次不會進行計算,會直接使用以前的 value 的值
當?shù)谝淮斡|發(fā)computedGetter 時,dirty 屬性的默認值是 true ,那是因為在初始化 computed watcher時候 Vue 將 dirty 屬性等于了 lazy 屬性,即為 true
知道 dirty 的默認值為 true,什么時候為 false 呢?我們接著來看 evalutate 具體的實現(xiàn)
evaluate方法evaluate 方法是 computed watcher 獨有的方法,代碼也只有短短2行
get方法
第一行執(zhí)行了 get 方法, get 方法是所有 watcher 用來求值的通用方法
get 主要就做了這三步
將當前這個 watcher 作為棧頂?shù)?watcher 推入棧
執(zhí)行getter方法
將這個 watcher 彈出棧
我們知道 Vue.js 會維護一個全局的棧用來存放 watcher ,每當觸發(fā)響應式變量內部的 getter 時,就會收集這個全局的棧的頂部的 watcher(即Dep.target),將這個 watcher 存入響應式變量內部保存的dep中
第一步通過 pushTarget 將當前的 computed watcher 推入全局的棧中,此時Dep.target就指向這個棧頂?shù)?computed watcher
第二步執(zhí)行 getter 方法, 對于 computed watcher,getter 方法就是計算屬性的函數(shù),執(zhí)行函數(shù)將返回的值賦值給 value 屬性,而當計算屬性的函數(shù)執(zhí)行時,如果內部含有其他的響應式變量,會觸發(fā)它們內部的 getter ,將第一步放入作為當前棧頂?shù)?computed watcher 存入響應式變量內部的dep對象中
注意響應式變量內部的 getter 和 getter 方法不是一個函數(shù)
第三步將這個 computed watcher 彈出全局的棧
之所以將這個 computed watcher 推入又彈出,是為了讓第二步執(zhí)行內部的 getter 時,能讓計算屬性函數(shù)內部依賴的響應式變量收集到這個 computed watcher
對于計算屬性來說,get 方法的作用就是進行求值
將dirty設為false執(zhí)行完 get 方法,即一旦計算屬性執(zhí)行過一次求值,就會將 dirty 屬性設為 false,如果下次又觸發(fā)了這個計算屬性的 getter 會直接跳過求值階段
結合文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/7324.html
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:插件開發(fā)前端掘金作者原文地址譯者插件是為應用添加全局功能的一種強大而且簡單的方式。提供了與使用掌控異步前端掘金教你使用在行代碼內優(yōu)雅的實現(xiàn)文件分片斷點續(xù)傳。 Vue.js 插件開發(fā) - 前端 - 掘金作者:Joshua Bemenderfer原文地址: creating-custom-plugins譯者:jeneser Vue.js插件是為應用添加全局功能的一種強大而且簡單的方式。插....
摘要:模塊化是隨著前端技術的發(fā)展,前端代碼爆炸式增長后,工程化所采取的必然措施。目前模塊化的思想分為和。特別指出,事件不等同于異步,回調也不等同于異步。將會討論安全的類型檢測惰性載入函數(shù)凍結對象定時器等話題。 Vue.js 前后端同構方案之準備篇——代碼優(yōu)化 目前 Vue.js 的火爆不亞于當初的 React,本人對寫代碼有潔癖,代碼也是藝術。此篇是準備篇,工欲善其事,必先利其器。我們先在代...
閱讀 3657·2021-10-12 10:11
閱讀 1021·2021-09-22 15:42
閱讀 3475·2019-08-30 13:06
閱讀 913·2019-08-29 17:05
閱讀 1658·2019-08-29 12:21
閱讀 2386·2019-08-29 11:31
閱讀 1141·2019-08-23 18:37
閱讀 1263·2019-08-23 14:58