深入理解 Vue Computed 计算属性
生活随笔
收集整理的這篇文章主要介紹了
深入理解 Vue Computed 计算属性
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Computed 計算屬性是 Vue 中常用的一個功能,我們今天來說一下他的執行過長
拿官網簡單的例子來看一下:
<div id="example"><p>Original message: "{{ message }}"</p><p>Computed reversed message: "{{ reversedMessage }}"</p> </div>var vm = new Vue({el: '#example',data: {message: 'Hello'},computed: {// a computed getterreversedMessage: function () {// `this` points to the vm instancereturn this.message.split('').reverse().join('')}} })
Vue 源碼分析 Computed 的實現原理
data 屬性初始化 getter setter:
// src/observer/index.js// 這里開始轉換 data 的 getter setter,原始值已存入到 __ob__ 屬性中 Object.defineProperty(obj, key, {enumerable: true,configurable: true,get: function reactiveGetter () {const value = getter ? getter.call(obj) : val// 判斷是否處于依賴收集狀態if (Dep.target) {// 建立依賴關系 dep.depend()...}return value},set: function reactiveSetter (newVal) {...// 依賴發生變化,通知到計算屬性重新計算 dep.notify()} })computed 計算屬性初始化
// src/core/instance/state.js// 初始化計算屬性 function initComputed (vm: Component, computed: Object) {...// 遍歷 computed 計算屬性for (const key in computed) {...// 創建 Watcher 實例// create internal watcher for the computed property.watchers[key] = new Watcher(vm, getter || noop, noop, computedWatcherOptions)// 創建屬性 vm.reversedMessage,并將提供的函數將用作屬性 vm.reversedMessage 的 getter,// 最終 computed 與 data 會一起混合到 vm 下,所以當 computed 與 data 存在重名屬性時會拋出警告 defineComputed(vm, key, userDef)...} }export function defineComputed (target: any, key: string, userDef: Object | Function) {...// 創建 get set 方法sharedPropertyDefinition.get = createComputedGetter(key)sharedPropertyDefinition.set = noop...// 創建屬性 vm.reversedMessage,并初始化 getter setter Object.defineProperty(target, key, sharedPropertyDefinition) }function createComputedGetter (key) {return function computedGetter () {const watcher = this._computedWatchers && this._computedWatchers[key]if (watcher) {if (watcher.dirty) {// watcher 暴露 evaluate 方法用于取值操作 watcher.evaluate()}// 同第1步,判斷是否處于依賴收集狀態if (Dep.target) {watcher.depend()}return watcher.value}} }無論是屬性還是計算屬性,都會生成一個對應的 watcher 實例。
// src/core/observer/watcher.js// 當通過 vm.reversedMessage 獲取計算屬性時,就會進到這個 getter 方法 get () {// this 指的是 watcher 實例// 將當前 watcher 實例暫存到 Dep.target,這就表示開啟了依賴收集任務pushTarget(this)let valueconst vm = this.vmtry {// 在執行 vm.reversedMessage 的函調函數時,會觸發屬性(步驟1)和計算屬性(步驟2)的 getter// 在這個執行過程中,就可以收集到 vm.reversedMessage 的依賴了value = this.getter.call(vm, vm)} catch (e) {if (this.user) {handleError(e, vm, `getter for watcher "${this.expression}"`)} else {throw e}} finally {if (this.deep) {traverse(value)}// 結束依賴收集任務 popTarget()this.cleanupDeps()}return value }上面多出提到了 dep.depend, dep.notify, Dep.target,那么 Dep 究竟是什么呢?
Dep 的代碼短小精悍,但卻承擔著非常重要的依賴收集環節。
// src/core/observer/dep.js export default class Dep {static target: ?Watcher;id: number;subs: Array<Watcher>;constructor () {this.id = uid++this.subs = []}addSub (sub: Watcher) {this.subs.push(sub)}removeSub (sub: Watcher) {remove(this.subs, sub)}depend () {if (Dep.target) {Dep.target.addDep(this)}}notify () {const subs = this.subs.slice()for (let i = 0, l = subs.length; i < l; i++) {// 更新 watcher 的值,與 watcher.evaluate() 類似,// 但 update 是給依賴變化時使用的,包含對 watch 的處理 subs[i].update()}} }// 當首次計算 computed 屬性的值時,Dep 將會在計算期間對依賴進行收集 Dep.target = null const targetStack = []export function pushTarget (_target: Watcher) {// 在一次依賴收集期間,如果有其他依賴收集任務開始(比如:當前 computed 計算屬性嵌套其他 computed 計算屬性),// 那么將會把當前 target 暫存到 targetStack,先進行其他 target 的依賴收集,if (Dep.target) targetStack.push(Dep.target)Dep.target = _target }export function popTarget () {// 當嵌套的依賴收集任務完成后,將 target 恢復為上一層的 Watcher,并繼續做依賴收集Dep.target = targetStack.pop() }?
總結
1.
?
?
?
?
轉載于:https://www.cnblogs.com/xuange306/p/9235131.html
總結
以上是生活随笔為你收集整理的深入理解 Vue Computed 计算属性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 生产管理MES系统框架
- 下一篇: MES系统介绍