中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

vue.js數據響應式原理是什么

發布時間:2022-08-03 16:52:37 來源:億速云 閱讀:133 作者:iii 欄目:開發技術

這篇文章主要介紹“vue.js數據響應式原理是什么”,在日常操作中,相信很多人在vue.js數據響應式原理是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”vue.js數據響應式原理是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

Object.defineProperty()

得力于 Object.defineProperty() 的特性,vue 的數據變化有別于 react 和小程序,是非侵入式的。詳細介紹可以看 MDN 文檔,這里特別說明幾點:

  • get / set 屬性是函數,出于習慣會被稱為 getter 函數 / setter 函數(Java,c++ 中都有這種慣例)

  • value 或 writable 和 get 或 set 是不能同時出現的,否則報錯

  • 注意區別 Object.defineProperties()

定義 defineReactive 函數

Object.defineProperty() 在使用 getter 和 setter 的時候,要想實現屬性的修改,需要借助一個變量周轉,如下面的 value,這就很麻煩。

const obj = {}
let value
Object.defineProperty(obj, 'a', {
  enumerable: true,
  configurable: true,
  get() {
    console.log('getter')
    return value
  },
  set(newValue) {
    value = newValue
    console.log('setter', newValue)
  }
})

所以定義了 defineReactive 函數,方便去給對象增加一個響應式屬性。這里創建一個閉包的環境:閉包一定要有內外兩個函數,外面這個函數 defineReactive 的 value 就形成了閉包。

const obj = {}
function defineReactive(data, key, value) {
  // 如果只傳了兩個參數,則讓 value 直接等于 data[key]
  if (arguments.length === 2) value = data[key]

  Object.defineProperty(data, key, {
    enumerable: true, // 可被枚舉(for...in 或 Object.keys 方法)
    configurable: true, // 可被配置,比如刪除
    get() {
      console.log('查看了' + key + '屬性')
      return value
    },
    set(newValue) {
      console.log('修改了' + key + '屬性')
      value = newValue
    }
  })
}

defineReactive(obj, 'a', 10)
console.log(obj.a)
obj.a = 11
console.log(obj.a)

得到的結果如下圖:

vue.js數據響應式原理是什么

遞歸偵測對象的全部屬性

我們自己寫一個能夠偵測對象全部屬性的庫
新建 index.js 作為主入口文件,用于測試效果,我們 let 一個對象 obj,目標是通過把 obj 作為參數傳給 observe 函數,即可實現對 obj 對象所有屬性的查看與修改的監測。

// index.js
import observe from './observe.js'
let obj = {
  a: {
    m: {
      n: 1
    }
  },
  b: 2
}
observe(obj)

流程分析

vue.js數據響應式原理是什么

observe 函數

observe 函數用于觀察一個對象(value)的屬性是否已被監測的(是否有 __ob__ 屬性),如果不是則讓其屬性成為響應式的(通過 new Observer(value))。
注意:之所以起了 __ob__ 這么奇怪的變量名,是為了保證不會與對象的原有屬性同名。

// observe.js
import Observer from './Observer.js'
export default (value) => {
  if (typeof value !== 'object') return
  if (value.__ob__ !== undefined) {
    // 暫時留空
  } else {
    new Observer(value)
  }
}

Observer 類

Observer 是一個類,一旦 new 了一個實例,則做 2 件事:

  • 給傳入的 value(其實是個對象) 添加 __ob__ 屬性,值為這次 new 的實例(也就是構造函數中的 this),因為希望 __ob__ 屬性是不可被枚舉的,所以用 def 函數處理。

  • 遍歷 value 的屬性,通過 defineReactive 函數將其變為響應式的

// Observer.js
import { def } from './utils.js'
import defineReactive from './defineReactive.js'

export default class Observer {
  constructor(value) {
    def(value, '__ob__', this, false)
    this.walk(value)
  }
  // 處理對象,讓對象的屬性變為響應式
  walk(value) {
    for (let key in value) {
      defineReactive(value, key)
    }
  }
}

def 函數定義如下:

export const def = (obj, key, value, enumerable) => {
  Object.defineProperty(obj, key, {
    value,
    enumerable,
    writable: true,
    configurable: true
  })
}

完善 defineReactive 函數

相較于前面定義的時候,在兩個地方添加了 observe(value),從而實現了遞歸偵測對象的全部屬性。這里的參數 value,就是已經被變為響應式的屬性的值,這個值如果是個對象,也需要被偵測,所以也要被 observe。

// defineReactive.js
import observe from './observe.js'

export default function defineReactive(data, key, value) {
  if (arguments.length === 2) value = data[key]

  // 注意這里不是傳 key 而是傳 value,因為 key 只是一個字符串,value 才是 key 指向的對象
  observe(value)
  // 讓 data 的 key 屬性變為響應式屬性
  Object.defineProperty(data, key, {
    enumerable: true, 
    configurable: true, 
    get() {
      console.log('查看了' + key + '屬性')
      return value
    },
    set(newValue) {
      console.log('修改了' + key + '屬性')
      value = newValue
      // 修改的屬性也需要被觀察,如果是對象需要被偵測
      observe(newValue)
    }
  })
}

至此,在 index.js 傳入 observe 的 obj 的每個屬性都是響應式的了

// index.js
...省略前面的代碼
obj.a.m = {
  y: 8
}
console.log(obj.a.m.y)

測試結果如下:

vue.js數據響應式原理是什么

One More Thing

普通對象也是有 getter 和 setter 的:

  • get propertyName(){} 用來得到當前屬性值的回調函數

  • set propertyName(){} 用來監視當前屬性值變化的回調函數

  • 下面的代碼中,屬性 a 稱為“數據屬性”,它只有一個簡單的值;屬性b這種用 getter 和 setter 方法定義的屬性稱為“存取器屬性”。

var num= {
    a: 2,
    get b(){
        return 2
    }
}

存取器屬性定義為一個或兩個與屬性同名的函數,這個函數定義不使用 function 關鍵字,而是使用 get 或 set,也沒有使用冒號將屬性名和函數體分開。

到此,關于“vue.js數據響應式原理是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

邹平县| 阜阳市| 古丈县| 故城县| 丰顺县| 高阳县| 淅川县| 岗巴县| 石首市| 绍兴县| 临西县| 阿合奇县| 宁南县| 界首市| 佛学| 海丰县| 南涧| 海阳市| 永清县| 济源市| 思南县| 宁城县| 安泽县| 泰宁县| 建宁县| 濮阳县| 东至县| 政和县| 林甸县| 青浦区| 汤原县| 黎川县| 莱州市| 吕梁市| 孟州市| 浦东新区| 融水| 清新县| 宜黄县| 丹凤县| 武陟县|