最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue.js數(shù)據(jù)響應式原理解析

 更新時間:2022年08月03日 10:14:54   作者:亦黑迷失  
這篇文章主要介紹了vue.js數(shù)據(jù)響應式原理解析,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下

Object.defineProperty()

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

  • get / set 屬性是函數(shù),出于習慣會被稱為 getter 函數(shù) / setter 函數(shù)(Java,c++ 中都有這種慣例)
  • value 或 writable 和 get 或 set 是不能同時出現(xiàn)的,否則報錯
  • 注意區(qū)別 Object.defineProperties()

定義 defineReactive 函數(shù)

Object.defineProperty() 在使用 getter 和 setter 的時候,要想實現(xiàn)屬性的修改,需要借助一個變量周轉,如下面的 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 函數(shù),方便去給對象增加一個響應式屬性。這里創(chuàng)建一個閉包的環(huán)境:閉包一定要有內(nèi)外兩個函數(shù),外面這個函數(shù) defineReactive 的 value 就形成了閉包。

const obj = {}
function defineReactive(data, key, value) {
  // 如果只傳了兩個參數(shù),則讓 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)

得到的結果如下圖:

遞歸偵測對象的全部屬性

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

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

流程分析

observe 函數(shù)

observe 函數(shù)用于觀察一個對象(value)的屬性是否已被監(jiān)測的(是否有 __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 的實例(也就是構造函數(shù)中的 this),因為希望 __ob__ 屬性是不可被枚舉的,所以用 def 函數(shù)處理。
  • 遍歷 value 的屬性,通過 defineReactive 函數(shù)將其變?yōu)轫憫降?/li>
// 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)
  }
  // 處理對象,讓對象的屬性變?yōu)轫憫?
  walk(value) {
    for (let key in value) {
      defineReactive(value, key)
    }
  }
}

def 函數(shù)定義如下:

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

完善 defineReactive 函數(shù)

相較于前面定義的時候,在兩個地方添加了 observe(value),從而實現(xiàn)了遞歸偵測對象的全部屬性。這里的參數(shù) value,就是已經(jīng)被變?yōu)轫憫降膶傩缘闹担@個值如果是個對象,也需要被偵測,所以也要被 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 屬性變?yōu)轫憫綄傩?
  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)

測試結果如下:

One More Thing

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

  • get propertyName(){} 用來得到當前屬性值的回調(diào)函數(shù)
  • set propertyName(){} 用來監(jiān)視當前屬性值變化的回調(diào)函數(shù)
  • 下面的代碼中,屬性 a 稱為“數(shù)據(jù)屬性”,它只有一個簡單的值;屬性b這種用 getter 和 setter 方法定義的屬性稱為“存取器屬性”。
var num= {
    a: 2,
    get b(){
        return 2
    }
}

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

到此這篇關于vue.js數(shù)據(jù)響應式原理解析的文章就介紹到這了,更多相關vue.js響應式原理 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Vue 多層組件嵌套二種實現(xiàn)方式(測試實例)

    Vue 多層組件嵌套二種實現(xiàn)方式(測試實例)

    本篇文章主要介紹了Vue組件嵌套二種實現(xiàn)方式(測試實例),具有一定的參考價值,代碼很簡單,感興趣的小伙伴們可以參考一下
    2017-09-09
  • 使用vue2.0創(chuàng)建的項目的步驟方法

    使用vue2.0創(chuàng)建的項目的步驟方法

    這篇文章主要介紹了使用vue2.0創(chuàng)建的項目的步驟方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • 基于vue2實現(xiàn)一個日歷組件

    基于vue2實現(xiàn)一個日歷組件

    最近在做一個類似課程表的需求,需要自制一個日歷來支持功能及展現(xiàn),就順便研究一下應該怎么開發(fā)日歷組件,下面這篇文章主要給大家介紹了關于如何基于vue2實現(xiàn)一個日歷組件的相關資料,需要的朋友可以參考下
    2022-12-12
  • vue自定義表單生成器form-create使用詳解

    vue自定義表單生成器form-create使用詳解

    這篇文章主要介紹了vue自定義表單生成器,可根據(jù)json參數(shù)動態(tài)生成表單,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07
  • vue-cli-service不是內(nèi)部或外部命令,也不是可運行的程序或批處理文件問題

    vue-cli-service不是內(nèi)部或外部命令,也不是可運行的程序或批處理文件問題

    在Vue項目構建過程中,如果遇到無法識別'vue-cli-service'命令的錯誤提示,通常是因為沒有全局安裝vue-cli,解決這個問題的步驟主要包括:首先檢查Vue版本,如果未安裝則先安裝Vue;其次全局安裝vue-cli;若在安裝過程中遇到cnpm命令找不到的情況
    2024-10-10
  • Vue3中的setup語法糖、computed函數(shù)、watch函數(shù)詳解

    Vue3中的setup語法糖、computed函數(shù)、watch函數(shù)詳解

    這篇文章主要介紹了Vue3中的setup語法糖、computed函數(shù)、watch函數(shù),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • Vue ​v-model相關知識總結

    Vue ​v-model相關知識總結

    這篇文章主要介紹了Vue ​v-model相關知識總結,幫助大家更好的理解和學習使用vue框架,感興趣的朋友可以了解下
    2021-01-01
  • vue實現(xiàn)組件之間傳值功能示例

    vue實現(xiàn)組件之間傳值功能示例

    這篇文章主要介紹了vue實現(xiàn)組件之間傳值功能,結合實例形式分析了vue.js父子組件之間相互傳值常見操作技巧,需要的朋友可以參考下
    2018-07-07
  • vue級聯(lián)選擇器的getCheckedNodes使用方式

    vue級聯(lián)選擇器的getCheckedNodes使用方式

    這篇文章主要介紹了vue級聯(lián)選擇器的getCheckedNodes使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • vue制作加載更多功能的正確打開方式

    vue制作加載更多功能的正確打開方式

    這篇文章是一篇Vue.js的教程,目標在于用一種常見的業(yè)務場景——分頁/無限加載,以及編寫過程中自己的錯誤寫法,分享給大家,幫助讀者更好的理解Vue.js中的一些設計思想。
    2016-10-10

最新評論

定陶县| 阆中市| 苏尼特右旗| 民县| 崇阳县| 罗源县| 错那县| 天全县| 大连市| 华宁县| 建湖县| 南京市| 同仁县| 双辽市| 海口市| 台南市| 长岭县| 禹州市| 苍溪县| 松桃| 额尔古纳市| 久治县| 岫岩| 台中县| 漠河县| 凤冈县| 马龙县| 中西区| 扎兰屯市| 汉川市| 新安县| 孝感市| 本溪市| 南岸区| 龙泉市| 博客| 共和县| 嵊州市| 昭苏县| 云阳县| 玉门市|