国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 網站 > 幫助中心 > 正文

稍微學一下Vue的數據響應式(Vue2及Vue3區別)

2024-07-09 22:41:45
字體:
來源:轉載
供稿:網友

什么是數據響應式

從一開始使用 Vue 時,對于之前的 jq 開發而言,一個很大的區別就是基本不用手動操作 dom,data 中聲明的數據狀態改變后會自動重新渲染相關的 dom。
換句話說就是 Vue 自己知道哪個數據狀態發生了變化及哪里有用到這個數據需要隨之修改。

因此實現數據響應式有兩個重點問題:

如何知道數據發生了變化? 如何知道數據變化后哪里需要修改?

對于第一個問題,如何知道數據發生了變化,Vue3 之前使用了 ES5 的一個 API Object.defineProperty Vue3 中使用了 ES6 的 Proxy,都是對需要偵測的數據進行 變化偵測 ,添加 getter 和 setter ,這樣就可以知道數據何時被讀取和修改。

第二個問題,如何知道數據變化后哪里需要修改,Vue 對于每個數據都收集了與之相關的 依賴 ,這里的依賴其實就是一個對象,保存有該數據的舊值及數據變化后需要執行的函數。每個響應式的數據變化時會遍歷通知其對應的每個依賴,依賴收到通知后會判斷一下新舊值有沒有發生變化,如果變化則執行回調函數響應數據變化(比如修改 dom)。

下面詳細分別介紹 Vue2 及 Vue3 的數據變化偵測及依賴收集。

Vue2

變化偵測

Object 的變化偵測

轉化響應式數據需要將 Vue 實例上 data 屬性中定義的數據通過遞歸將所有屬性都轉化為 getter/setter 的形式,Vue 中定義了一個 Observer 類來做這個事情。

function def(obj, key, val, enumerable) { Object.defineProperty(obj, key, {  value: val,  enumerable: !!enumerable,  writable: true,  configurable: true })}class Observer { constructor(value) {  this.value = value;  def(value, '__ob__', this);  if (!Array.isArray(value)) {   this.walk(value);  } } walk(obj) {  for (const [key, value] of Object.entries(obj)) {   defineReactive(obj, key, value);  } }}

直接將一個對象傳入 new Observer() 后就對每項屬性都調用 defineReactive 函數添加變化偵測,下面定義這個函數:

function defineReactive(data, key, val) { let childOb = observe(val); Object.defineProperty(data, key, {  enumerable: true,  configurable: true,  get: function () {   // 讀取 data[key] 時觸發   console.log('getter', val);   return val;  },  set: function (newVal) {   // 修改 data[key] 時觸發   console.log('setter', newVal);   if (val === newVal) {    return;   }   val = newVal;  } })}function observe(value, asRootData) { if (typeof val !== 'object') {  return; } let ob; if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {  ob = value.__ob__; } else {  ob = new Observer(val); } return ob;}

函數中判斷如果是對象則遞歸調用 Observer 來實現所有屬性的變化偵測,根據 __ob__ 屬性判斷是否已處理過,防止多次重復處理,Observer 處理過后會給數據添加這個屬性,下面寫一個對象試一下:

const people = { name: 'c', age: 12, parents: {  dad: 'a',  mom: 'b' }, mates: ['d', 'e']};new Observer(people);people.name; // getter cpeople.age++; // getter 12 setter 13people.parents.dad; // getter {} getter a

打印 people 可以看到所有屬性添加了 getter/setter 方法,讀取 name 屬性時打印了 people.age++ 修改 age 時打印了 getter 12 setter 13 說明 people 的屬性已經被全部成功代理監聽。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 通州市| 聂拉木县| 寻乌县| 铜梁县| 蓬溪县| 祁连县| 交城县| 白玉县| 绿春县| 特克斯县| 怀远县| 通州市| 余姚市| 新安县| 临颍县| 阿拉善右旗| 邢台县| 五河县| 开远市| 汝阳县| 麻江县| 宁南县| 扶余县| 望江县| 施甸县| 五河县| 临沧市| 定边县| 西吉县| 乌苏市| 淮安市| 白银市| 南开区| 勐海县| 石狮市| 泸州市| 重庆市| 富蕴县| 香格里拉县| 炉霍县| 大冶市|