Vue2源碼解讀(3) - $set()使用及實現原理


Vue2源碼解讀 - $set()使用及實現原理

  • 當我們給響應式的對象新增屬性時,新增的屬性並不會渲染到頁面中
  • 對於響應式的數組,增加元素、修改數組長度時,數組的這些變化也不會反映到頁面中

那么如何讓新增的對象或數組實現響應式及時渲染頁面呢?

使用this.$set()

官方定義

Vue 不允許在已經創建的實例上動態添加新的根級響應式屬性 (root-level reactive property)。然而它可以使用 Vue.set(object, key, value)方法將響應屬性添加到嵌套的對象上

// Vue.set(object, key, value) 
<template>
    <div>{{obj.k}}</div>
</template>
<script>
export default {
    data() {
        return {
            obj: {
                s: '1',
                z: '2'
            }
        }   
    },
    mounted() {
        this.$set(this.obj, 'k', '3')
    }
}
</script>

$set原理

直接看源碼

function set(target: Array<any> | Object, key: any, val: any): any {
  // isUndef 是判斷 target 是不是等於 undefined 或者 null 。
  //isPrimitive 是判斷 target 的數據類型是不是 string、number、symbol、boolean 中的一種
  if (process.env.NODE_ENV !== 'production' &&
    (isUndef(target) || isPrimitive(target))
  ) {
    warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`)
  }

  // 數組的處理
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key)
    target.splice(key, 1, val)
    return val
  }

  // 對象,並且該屬性原來已存在於對象中,則直接更新
  if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }

  // vue給響應式對象(比如 data 里定義的對象)都加了一個 __ob__ 屬性,
  // 如果一個對象有這個 __ob__ 屬性,那么就說明這個對象是響應式對象,我們修改對象已有屬性的時候就會觸發頁面渲染。
  // 非 data 里定義的就不是響應式對象。
  const ob = (target: any).__ob__

  if (target._isVue || (ob && ob.vmCount)) {
    process.env.NODE_ENV !== 'production' && warn(
      'Avoid adding reactive properties to a Vue instance or its root $data ' +
      'at runtime - declare it upfront in the data option.'
    )
    return val
  }

  // 不是響應式對象
  if (!ob) {
    target[key] = val
    return val
  }

  // 是響應式對象,進行依賴收集
  defineReactive(ob.value, key, val)

  // 觸發更新視圖
  ob.dep.notify()
  return val
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM