聊聊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 = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ] 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 'push': case 'unshift': inserted = args break case 'splice': 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方法對數組和物件的處理本質上的一樣的,對新增的值添加回應然後手動觸發派發更新。
以上是聊聊Vue中$set是如何實現的?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

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

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

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

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

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

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

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

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