目錄
#應用程式場景
set實作
#陣列實作回應
物件實作回應
總結
首頁 web前端 Vue.js 聊聊Vue中$set是如何實現的?

聊聊Vue中$set是如何實現的?

Dec 15, 2022 pm 09:26 PM
vue.js

聊聊Vue中$set是如何實現的?

在日常開發中,$set的也是一個非常實用的API,因為Vue2實作響應式的核心是利用了ES5的Object.defineProperty,當我們透過直接修改數組下標更改數組或為物件添加新的屬性,這時候Object.defineproperty是監聽不到資料的變化的,這時候大家就會用上 $set,讓修改的操作也實現響應,我們知其然更要知其所以然,接下來看一下Vue中的$set是如何實現的。 【相關推薦:vuejs影片教學web前端開發

#應用程式場景

 let dataArr = ["item1"];
 let dataObject = {
      name: "ccs"
    };

    dataArr[2] = "item2";
    dataObject.age = 22;
    响应失败,页面没有显示更新新增的数据

    this.$set(this.dataArr,2,'item2')
    this.$set(this.dataObject,'age',22)
    响应成功,页面显示更新新增的数据
登入後複製

set實作

接下來我們來看看$set在Vue中的定義

function set(target: Array<any> | Object, key: any, val: any): any {
  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;
  }
  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;
}
登入後複製

在原始碼中先判斷set的目標是否是undefined基本型別如果是 undefined基本類型就報錯,
因為使用者不應該往undefined和基本類型中set東西
然後又判斷了目標是否是數組與key是不是合法的index,合法的index是指值為大於等於0的整數,
如果兩個條件都成立就對目標數組調用splice方法插入或者修改數組
這裡的splice不是普通的splice是王維詩裡的splice,是被vue代理人重寫過的splice

#陣列實作回應

$set實作陣列修改回應的方式是代理人重寫的陣列的一部分方法,接下來我們看一下具體實作

const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)

const methodsToPatch = [
  &#39;push&#39;,
  &#39;pop&#39;,
  &#39;shift&#39;,
  &#39;unshift&#39;,
  &#39;splice&#39;,
  &#39;sort&#39;,
  &#39;reverse&#39;
]
function def(obj, key, val, enumerable) {
    Object.defineProperty(obj, key, {
        value: val,
        enumerable: !!enumerable,
        writable: true,
        configurable: true
    });
}
methodsToPatch.forEach(function (method) {
  const original = arrayProto[method]
  def(arrayMethods, method, function mutator (...args) {
    const result = original.apply(this, args)
    const ob = this.__ob__
    let inserted
    switch (method) {
      case &#39;push&#39;:
      case &#39;unshift&#39;:
        inserted = args
        break
      case &#39;splice&#39;:
        inserted = args.slice(2)
        break
    }
    if (inserted) ob.observeArray(inserted)
    ob.dep.notify()
    return result
  })
})
登入後複製

vue中代理重寫的不只是splice,有push、pop、shift、unshift、splice、sort、reverse這七個方法, 首先執行了const result = original.apply(this, args)#執行原本數組的方法並取得它的值,接下來判斷如果是往數組中新增值就將新加入的值也實作響應式,
最後一步拿到這個陣列的_ob_物件_ob_ 裡的dep進行派發更新。
想深入了解vue的回應式可以查閱往期文章
面試官問你Vue2的回應式原理,你怎麼答? - 掘金(juejin.cn)

物件實作回應

$set中下半部的邏輯就是用來處理物件回應的,我們接著往下看

  if (key in target && !(key in Object.prototype)) {
    target[key] = val;
    return val;
  }
  const ob = (target: any).__ob__;
  if (!ob) {
    target[key] = val;
    return val;
  }
  defineReactive(ob.value, key, val);
  ob.dep.notify();
  return val;
登入後複製

首先判斷了屬性如果在目標物件中直接return結束邏輯,
因為vue只有在新增目標物件中原本沒有的屬性時才會失去回應
例如let obj={}  obj.name='ccs'
vue在初始化的時候會將data裡的所有屬性都變成響應式,如果的值是物件或陣列則會new一個Observer實例儲存在__ob__,想深入了解vue的回應式可以查閱往期文章
面試官問你Vue2的響應式原理,你怎麼答? - 掘金(juejin.cn)
拿到這個物件的_ob_進行判斷,如果不存在就表示是未經過vue初始化的普通物件而不是回應式物件否則就手動透過defineReactive為屬性新增get方法與set方法實作回應
然後手動呼叫dep裡的notify()發布更新。

總結

vue中$set方法對數組和物件的處理本質上的一樣的,對新增的值添加回應然後手動觸發派發更新。

(學習影片分享:vuejs入門教學程式設計基礎影片

以上是聊聊Vue中$set是如何實現的?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

深入探討vite是怎麼解析.env檔的 深入探討vite是怎麼解析.env檔的 Jan 24, 2023 am 05:30 AM

使用vue框架開發前端專案時,我們部署的時候都會部署多套環境,往往開發、測試以及線上環境呼叫的介面網域都是不一樣的。如何能做到區分呢?那就是使用環境變數和模式。

圖文詳解如何在Vue專案中整合Ace程式碼編輯器 圖文詳解如何在Vue專案中整合Ace程式碼編輯器 Apr 24, 2023 am 10:52 AM

Ace 是一個用 JavaScript 寫的可嵌入程式碼編輯器。它與 Sublime、Vim 和 TextMate 等原生編輯器的功能和效能相符。它可以很容易地嵌入到任何網頁和 JavaScript 應用程式中。 Ace 被維護為Cloud9 IDE的主要編輯器 ,並且是 Mozilla Skywriter (Bespin) 專案的繼承者。

vue中組件化和模組化有什麼區別 vue中組件化和模組化有什麼區別 Dec 15, 2022 pm 12:54 PM

組件化和模組化的區別:模組化是從程式碼邏輯的角度進行劃分的;方便程式碼分層開發,確保每個每個功能模組的職能一致。元件化是從UI介面的角度進行規劃;前端的元件化,方便UI元件的重複使用。

探討如何在Vue3中撰寫單元測試 探討如何在Vue3中撰寫單元測試 Apr 25, 2023 pm 07:41 PM

在當今前端開發中,Vue.js 已經成為了一個非常流行的框架。隨著 Vue.js 的不斷發展,單元測試變得越來越重要。今天,我們將探討如何在 Vue.js 3 中編寫單元測試,並提供一些最佳實踐和常見的問題及解決方案。

深入聊聊vue3中的reactive() 深入聊聊vue3中的reactive() Jan 06, 2023 pm 09:21 PM

前言:在vue3的開發中,reactive是提供實現響應式資料的方法。日常開發這個是使用頻率很高的api。這篇文章筆者就來探索其內部運作機制。

Vue中JSX語法和模板語法的簡單比較(優劣勢分析) Vue中JSX語法和模板語法的簡單比較(優劣勢分析) Mar 23, 2023 pm 07:53 PM

在Vue.js中,開發人員可以使用兩種不同的語法來建立使用者介面:JSX語法和範本語法。這兩種文法各有優劣,以下就來探討它們的差異和優劣勢。

怎麼查詢目前vue的版本 怎麼查詢目前vue的版本 Dec 19, 2022 pm 04:55 PM

查詢目前vue版本的兩種方法:1、在cmd控制台內,執行「npm list vue」指令查詢版本,輸出結果就是vue的版本號資訊;2、在專案中找到並開啟package.json文件,查找「dependencies」項目即可看到vue的版本資訊。

淺析Vue3動態組件怎麼進行異常處理 淺析Vue3動態組件怎麼進行異常處理 Dec 02, 2022 pm 09:11 PM

Vue3動態元件怎麼進行異常處理?以下這篇文章帶大家聊聊Vue3 動態元件異常處理的方法,希望對大家有幫助!

See all articles