亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

Vue響應式原理介紹

2023-05-26 07:01:05
77
0

Vue.js 是當前流行的一款漸進式 JavaScript 框架,其主要特點之一是響應式編程。Vue.js 的響應式系統讓數據的變化驅動了頁面的變化,降低了前端編程的復雜度。在本文中,我們將介紹 Vue.js 的響應式原理。

Vue.js 的響應式系統

當一個 Vue.js 應用啟動時,Vue.js 會將所有的數據轉換為響應式數據,這些響應式數據會與模板中的 DOM 元素建立關聯,當發生數據更新時,Vue.js 會自動更新模板。這種機制被稱為“響應式系統”,Vue.js 中使用一個 Watcher 來觀察每一個響應式數據,當數據改變時觸發更新。

響應式數據的創建

Vue.js 中采用了 Object.defineProperty 方法來實現響應式數據。Object.defineProperty 方法可以在一個對象上定義一個新屬性或修改一個已有屬性,包含以下幾個參數:

  • obj:要在其上定義屬性的對象;

  • prop:要定義或修改的屬性的名稱;

  • descriptor:將被定義或修改的屬性的描述符。

Vue.js 將每一個響應式數據對象添加一個標識,并在其中存儲了關于該對象的觀察者 Watcher 信息。Vue.js 通過該方法來監聽數據的變化并觸發更新。

以下代碼展示了如何使用 Object.defineProperty 來創建響應式數據:

var obj = {}
Object.defineProperty(obj, 'prop', {
 get: function () {
   return value
},
 set: function (newValue) {
   value = newValue
}
})

依賴收集

依賴收集是 Vue.js 最重要的特性之一。當 Vue.js 遇到了一個取值操作(如 obj.prop),它會通過一個全局定義的變量(稱為 Dep)將該取值操作與當前激活的 Watcher 進行關聯。這個 Watcher 就是數據的依賴。

當響應式數據發生改變時,該數據的 Set 方法會通知所有的 Watcher 更新,這些 Watcher 就會根據自身的依賴重新計算其所對應的組件,然后更新視圖。

下面是一個代碼示例:

function defineReactive (obj, key, val) {
 Object.defineProperty(obj, key, {
   get: function () {
     if (Dep.target) {
       Dep.target.addDep(dep)
    }
     return val
  },
   set: function (newVal) {
     if (val !== newVal) {
       val = newVal
       dep.notify()
    }
  }
})
}

其中,addDep 方法用于將當前 Watcher 加入到依賴中。

Watcher

Watcher 是 Vue.js 實現響應式編程的核心。它的作用是存儲被觀察的數據以及依賴,當被觀察的數據被修改時,Watcher 會通知所有的依賴重新計算。

下面是一個 Watcher 的基礎實現:

function Watcher (vm, expOrFn, cb) {
 this.cb = cb
 this.vm = vm
 this.expOrFn = expOrFn
 this.depIds = []
 if (typeof expOrFn === 'function') {
   this.getter = expOrFn
} else {
   this.getter = this.parseGetter(expOrFn.trim())
}
 this.value = this.get()
}
?
Watcher.prototype = {
 update: function () {
   this.run()
},
 run: function () {
   var value = this.get()
   var oldValue = this.value
   if (value !== oldValue) {
     this.value = value
     this.cb.call(this.vm, value, oldValue)
  }
},
 get: function () {
   Dep.target = this
   var value = this.getter.call(this.vm, this.vm)
   Dep.target = null
   return value
},
 addDep: function (dep) {
   var id = dep.id
   if (this.depIds.indexOf(id) === -1) {
     this.depIds.push(id)
     dep.addSub(this)
  }
},
 parseGetter: function (exp) {
   if (/[^\w.$]/.test(exp)) return
?
   var exps = exp.split('.')
?
   return function (obj) {
     for (var i = 0; i < exps.length; i++) {
       obj = obj[exps[i]]
    }
     return obj
  }
}
}

響應式系統的局限性

雖然 Vue.js 的響應式系統可以很好地工作,但是也有一些局限性。比如:

  • 數組變化時 Vue.js 無法識別以下操作:直接通過數組下標設置元素,Array.prototype.push(),Array.prototype.pop(),Array.prototype.shift(),Array.prototype.unshift(),Array.prototype.splice(),Array.prototype.sort(),Array.prototype.reverse()

Vue3的響應式

以上主要是Vue2.x的響應式原理,下面是Vue3.x的響應式原理。

Vue3.x引入了一個新的響應式API,即Proxy API,來代替Vue2.x中使用的Object.defineProperty實現。使用Proxy API可以使得Vue3.x在性能上更加優越,并且可以更靈活地處理動態添加和刪除的屬性,以及能實現對Map、Set等JavaScript數據結構的響應式處理。

Vue3.x中,響應式系統的核心依然是劫持核心對象的getter方法,來監聽屬性值的變化,但是與Vue2.x不一樣的是,Vue3.x使用了Proxy API,將一個對象包裝在一個代理層之中,從而在代理層進行攔截和監聽。

下面是Vue3.x中響應式系統的實現代碼:

const mutableHandlers = {
 get: function(target, key) {
   const res = Reflect.get(target, key)
   track(target, key) // 響應式收集依賴
   return isObject(res) ? reactive(res) : res
},
 set: function(target, key, val) {
   const oldVal = Reflect.get(target, key)
   val = isObject(val) ? reactive(val) : val
   const result = Reflect.set(target, key, val)
   if (!oldVal) {
     // 新添加的屬性
     trigger(target, 'add', key, val)
     trigger(target, 'set', key, val)
  } else if (val !== oldVal) {
     // 已有的屬性
     trigger(target, 'set', key, val, oldVal)
  }
   return result
},
 deleteProperty: function(target, key) {
   const result = Reflect.deleteProperty(target, key)
   if (result) {
     trigger(target, 'delete', key)
  }
   return result
}
}
?
function reactive(obj) {
 if (!isObject(obj)) {
   return obj
}
 return new Proxy(obj, mutableHandlers)
}

在這個實現中,mutableHandlers是一個對象,其中的get和set方法是攔截屬性訪問和設置的方法。當使用reactive函數劫持一個對象時,會返回該對象的代理對象,該代理對象可以處理這些操作,從而使得可以在這些操作中收集依賴和觸發更新。

在創建代理對象的過程中,對對象進行遞歸處理,將對象中的所有屬性都轉換為響應式屬性。當訪問代理對象中的一個屬性值時,該值會被代理,并且如果該值是一個對象,則會遞歸創建它的代理對象。

除了使用Proxy API來實現響應式系統之外,Vue3.x的響應式系統還引入了新的API,比如refcomputed。這些API可以幫助我們更加方便地處理響應式數據,并且可以減少開發的工作量、減少代碼的復雜度。

總結

本文主要介紹了Vue2.x和Vue3.x響應式系統的實現原理。Vue3.x采用了新的Proxy API替代了Object.defineProperty API,提升了性能,解決了某些場景下響應式更新不正確的問題,并且可以處理動態屬性和Map、Set等數據結構的響應式。此外,新增了`ref`和`computed` API,提供更好的性能和易用性。總的來說,Vue3.x響應式系統在性能、靈活性和易用性方面都有顯著的改進,可以更高效地創建易于維護的響應式應用。

0條評論
0 / 1000
張****亮
9文章數
0粉絲數
張****亮
9 文章 | 0 粉絲
原創

Vue響應式原理介紹

2023-05-26 07:01:05
77
0

Vue.js 是當前流行的一款漸進式 JavaScript 框架,其主要特點之一是響應式編程。Vue.js 的響應式系統讓數據的變化驅動了頁面的變化,降低了前端編程的復雜度。在本文中,我們將介紹 Vue.js 的響應式原理。

Vue.js 的響應式系統

當一個 Vue.js 應用啟動時,Vue.js 會將所有的數據轉換為響應式數據,這些響應式數據會與模板中的 DOM 元素建立關聯,當發生數據更新時,Vue.js 會自動更新模板。這種機制被稱為“響應式系統”,Vue.js 中使用一個 Watcher 來觀察每一個響應式數據,當數據改變時觸發更新。

響應式數據的創建

Vue.js 中采用了 Object.defineProperty 方法來實現響應式數據。Object.defineProperty 方法可以在一個對象上定義一個新屬性或修改一個已有屬性,包含以下幾個參數:

  • obj:要在其上定義屬性的對象;

  • prop:要定義或修改的屬性的名稱;

  • descriptor:將被定義或修改的屬性的描述符。

Vue.js 將每一個響應式數據對象添加一個標識,并在其中存儲了關于該對象的觀察者 Watcher 信息。Vue.js 通過該方法來監聽數據的變化并觸發更新。

以下代碼展示了如何使用 Object.defineProperty 來創建響應式數據:

var obj = {}
Object.defineProperty(obj, 'prop', {
 get: function () {
   return value
},
 set: function (newValue) {
   value = newValue
}
})

依賴收集

依賴收集是 Vue.js 最重要的特性之一。當 Vue.js 遇到了一個取值操作(如 obj.prop),它會通過一個全局定義的變量(稱為 Dep)將該取值操作與當前激活的 Watcher 進行關聯。這個 Watcher 就是數據的依賴。

當響應式數據發生改變時,該數據的 Set 方法會通知所有的 Watcher 更新,這些 Watcher 就會根據自身的依賴重新計算其所對應的組件,然后更新視圖。

下面是一個代碼示例:

function defineReactive (obj, key, val) {
 Object.defineProperty(obj, key, {
   get: function () {
     if (Dep.target) {
       Dep.target.addDep(dep)
    }
     return val
  },
   set: function (newVal) {
     if (val !== newVal) {
       val = newVal
       dep.notify()
    }
  }
})
}

其中,addDep 方法用于將當前 Watcher 加入到依賴中。

Watcher

Watcher 是 Vue.js 實現響應式編程的核心。它的作用是存儲被觀察的數據以及依賴,當被觀察的數據被修改時,Watcher 會通知所有的依賴重新計算。

下面是一個 Watcher 的基礎實現:

function Watcher (vm, expOrFn, cb) {
 this.cb = cb
 this.vm = vm
 this.expOrFn = expOrFn
 this.depIds = []
 if (typeof expOrFn === 'function') {
   this.getter = expOrFn
} else {
   this.getter = this.parseGetter(expOrFn.trim())
}
 this.value = this.get()
}
?
Watcher.prototype = {
 update: function () {
   this.run()
},
 run: function () {
   var value = this.get()
   var oldValue = this.value
   if (value !== oldValue) {
     this.value = value
     this.cb.call(this.vm, value, oldValue)
  }
},
 get: function () {
   Dep.target = this
   var value = this.getter.call(this.vm, this.vm)
   Dep.target = null
   return value
},
 addDep: function (dep) {
   var id = dep.id
   if (this.depIds.indexOf(id) === -1) {
     this.depIds.push(id)
     dep.addSub(this)
  }
},
 parseGetter: function (exp) {
   if (/[^\w.$]/.test(exp)) return
?
   var exps = exp.split('.')
?
   return function (obj) {
     for (var i = 0; i < exps.length; i++) {
       obj = obj[exps[i]]
    }
     return obj
  }
}
}

響應式系統的局限性

雖然 Vue.js 的響應式系統可以很好地工作,但是也有一些局限性。比如:

  • 數組變化時 Vue.js 無法識別以下操作:直接通過數組下標設置元素,Array.prototype.push(),Array.prototype.pop(),Array.prototype.shift(),Array.prototype.unshift(),Array.prototype.splice(),Array.prototype.sort(),Array.prototype.reverse()

Vue3的響應式

以上主要是Vue2.x的響應式原理,下面是Vue3.x的響應式原理。

Vue3.x引入了一個新的響應式API,即Proxy API,來代替Vue2.x中使用的Object.defineProperty實現。使用Proxy API可以使得Vue3.x在性能上更加優越,并且可以更靈活地處理動態添加和刪除的屬性,以及能實現對Map、Set等JavaScript數據結構的響應式處理。

Vue3.x中,響應式系統的核心依然是劫持核心對象的getter方法,來監聽屬性值的變化,但是與Vue2.x不一樣的是,Vue3.x使用了Proxy API,將一個對象包裝在一個代理層之中,從而在代理層進行攔截和監聽。

下面是Vue3.x中響應式系統的實現代碼:

const mutableHandlers = {
 get: function(target, key) {
   const res = Reflect.get(target, key)
   track(target, key) // 響應式收集依賴
   return isObject(res) ? reactive(res) : res
},
 set: function(target, key, val) {
   const oldVal = Reflect.get(target, key)
   val = isObject(val) ? reactive(val) : val
   const result = Reflect.set(target, key, val)
   if (!oldVal) {
     // 新添加的屬性
     trigger(target, 'add', key, val)
     trigger(target, 'set', key, val)
  } else if (val !== oldVal) {
     // 已有的屬性
     trigger(target, 'set', key, val, oldVal)
  }
   return result
},
 deleteProperty: function(target, key) {
   const result = Reflect.deleteProperty(target, key)
   if (result) {
     trigger(target, 'delete', key)
  }
   return result
}
}
?
function reactive(obj) {
 if (!isObject(obj)) {
   return obj
}
 return new Proxy(obj, mutableHandlers)
}

在這個實現中,mutableHandlers是一個對象,其中的get和set方法是攔截屬性訪問和設置的方法。當使用reactive函數劫持一個對象時,會返回該對象的代理對象,該代理對象可以處理這些操作,從而使得可以在這些操作中收集依賴和觸發更新。

在創建代理對象的過程中,對對象進行遞歸處理,將對象中的所有屬性都轉換為響應式屬性。當訪問代理對象中的一個屬性值時,該值會被代理,并且如果該值是一個對象,則會遞歸創建它的代理對象。

除了使用Proxy API來實現響應式系統之外,Vue3.x的響應式系統還引入了新的API,比如refcomputed。這些API可以幫助我們更加方便地處理響應式數據,并且可以減少開發的工作量、減少代碼的復雜度。

總結

本文主要介紹了Vue2.x和Vue3.x響應式系統的實現原理。Vue3.x采用了新的Proxy API替代了Object.defineProperty API,提升了性能,解決了某些場景下響應式更新不正確的問題,并且可以處理動態屬性和Map、Set等數據結構的響應式。此外,新增了`ref`和`computed` API,提供更好的性能和易用性。總的來說,Vue3.x響應式系統在性能、靈活性和易用性方面都有顯著的改進,可以更高效地創建易于維護的響應式應用。

文章來自個人專欄
文章 | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0