Vue簡(jiǎn)介
Vue.js 是一個(gè)開源的漸進(jìn)式 JavaScript 前端框架,主要用于構(gòu)建用戶界面和單頁應(yīng)用程序(SPA)。Vue.js 可以輕松地與其他庫或現(xiàn)有項(xiàng)目集成使用,并被認(rèn)為是開發(fā)響應(yīng)式數(shù)據(jù)驅(qū)動(dòng)的現(xiàn)代 Web 應(yīng)用的一種有效方式。
Vue.js 的核心特點(diǎn):
- 響應(yīng)式數(shù)據(jù)綁定:Vue.js 可以通過對(duì)數(shù)據(jù)進(jìn)行雙向綁定來響應(yīng)用戶輸入和頁面變化。
- 組件化:Vue.js 使得開發(fā)者可以將單個(gè)組件變成一個(gè)獨(dú)立的模塊,組件性能優(yōu)良且可以重復(fù)利用。
- 基于模板的語法:Vue.js 提供了一套模板語法,使得開發(fā)者可以簡(jiǎn)單地編寫 HTML 模板,并將其與 Vue.js 組件綁定。
Vue2的響應(yīng)式原理
Vue2 的響應(yīng)式原理建立在 ES5 的 Object.defineProperty()
上,該方法可以定義對(duì)象的屬性,并對(duì)其進(jìn)行劫持,當(dāng)屬性值發(fā)生變化時(shí),Vue 可以檢測(cè)到該變化并重新渲染相應(yīng)的頁面內(nèi)容。
具體實(shí)現(xiàn)原理如下:
- 在 Vue 的初始化階段,Vue 會(huì)對(duì)傳入的
data
對(duì)象進(jìn)行遞歸劫持,將data
對(duì)象的所有屬性都轉(zhuǎn)換成getter/setter
形式。 - 當(dāng)頁面中使用數(shù)據(jù)時(shí),Vue 會(huì)通過訪問屬性的方式觸發(fā)
getter
函數(shù),從而將當(dāng)前的Watcher
(觀察者)對(duì)象加入到當(dāng)前屬性的依賴中。 - 當(dāng)數(shù)據(jù)發(fā)生變化時(shí),Vue 會(huì)通過監(jiān)聽器檢測(cè)到變化,并觸發(fā)對(duì)應(yīng)屬性的
setter
函數(shù),從而通知該屬性下所有的依賴Watcher
更新; -
Watcher
對(duì)象被通知后,會(huì)向?qū)?yīng)的組件發(fā)送消息通知需要重新渲染視圖,從而實(shí)現(xiàn)整個(gè)頁面的更新。
需要注意,Vue2 只能監(jiān)聽對(duì)象屬性的變化,并不能監(jiān)聽到添加/刪除對(duì)象屬性、數(shù)組方法的變化,因此我們可以使用 Vue.set()
或者 Vue.delete()
方法來更新對(duì)象屬性,但是只能使用原生 JavaScript 數(shù)組的 push()
、 pop()
、splice()
、 shift()
、 unshift()
方法等來操作數(shù)組。
Vue2數(shù)據(jù)劫持的示例代碼如下:
const data = { msg: 'Hello Vue' }
Object.defineProperty(data, 'msg', {
get() {
console.log('get');
return val;
},
set(newValue) {
console.log('set', newValue);
val = newValue;
}
})
Object.defineProperty()詳解
Object.defineProperty() 是在 ES5 中新增的一個(gè)方法,用于為對(duì)象定義新的屬性或修改對(duì)象的屬性,其語法如下:
Object.defineProperty(obj, prop, descriptor)
其中的參數(shù)含義:
- obj:要定義屬性的對(duì)象。
- prop:要定義或修改的屬性的名稱。
- descriptor:需要定義或修改的屬性描述符對(duì)象。
屬性描述符對(duì)象中包含以下可選屬性:
- value:屬性的值,默認(rèn)為 undefined。
- writable:如果為 true,則該屬性的值可以被賦值運(yùn)算符改變,默認(rèn)為 false。
- enumerable:如果為 true,則該屬性可以在枚舉對(duì)象屬性時(shí)被枚舉,默認(rèn)為 false。
- configurable:如果為 true,則可以使用 Object.defineProperty() 方法修改該屬性的描述符,默認(rèn)為 false。
- get:屬性讀取方法。
- set:屬性賦值方法。
Object.defineProperty()的缺點(diǎn)
-
無法監(jiān)聽數(shù)組的變化
Vue2
把會(huì)修改原來數(shù)組的方法定義為變異方法。
變異方法例如push、pop、shift、unshift、splice、sort、reverse
等,是無法觸發(fā)set
的。
非變異方法,例如filter,concat,slice
等,它們都不會(huì)修改原始數(shù)組,而會(huì)返回一個(gè)新的數(shù)組。Vue2
的做法是把這些變異方法重寫來實(shí)現(xiàn)監(jiān)聽數(shù)組變化。 - 必須遍歷對(duì)象的每個(gè)屬性
使用Object.defineProperty
多數(shù)情況下要配合Object.keys
和遍歷,于是就多了一層嵌套。
并且由于遍歷的原因,假如對(duì)象上的某個(gè)屬性并不需要“劫持”,但此時(shí)依然會(huì)對(duì)其添加“劫持”。 - 必須深層遍歷嵌套的對(duì)象
當(dāng)一個(gè)對(duì)象為深層嵌套的時(shí)候,必須進(jìn)行逐層遍歷,直到把每個(gè)對(duì)象的每個(gè)屬性都調(diào)用Object.defineProperty()
為止。
Vue3的響應(yīng)式原理
Vue3 的響應(yīng)式原理主要使用了 ES6 的 Proxy
代替了 Vue2 中的 Object.defineProperty()
,從而實(shí)現(xiàn)了更加高效和強(qiáng)大的數(shù)據(jù)劫持和響應(yīng)式。
Proxy 對(duì)象可以通過對(duì)訪問和修改數(shù)據(jù)的攔截來實(shí)現(xiàn)數(shù)據(jù)劫持。而 Reflect 對(duì)象則提供了更加靈活和易用的數(shù)據(jù)操作方法,比如可以使用 Reflect.has() 來檢查對(duì)象是否有某個(gè)屬性,使用 Reflect.defineProperty() 來代替 Object.defineProperty()。
具體實(shí)現(xiàn)原理如下:
-
在 Vue3 的初始化階段,Vue3 會(huì)對(duì)傳入的
data
對(duì)象通過使用Proxy
對(duì)象進(jìn)行代理,即使用new Proxy(target, handler)
,其中target
是被代理的對(duì)象,handler
是一個(gè)對(duì)象,用來定義代理target
中的操作。 -
當(dāng)頁面中使用數(shù)據(jù)時(shí),Vue3 會(huì)觸發(fā)
get
操作,代理對(duì)象handler.get()
會(huì)被調(diào)用,進(jìn)而讓handler
捕獲該操作,并將當(dāng)前的Watcher
(觀察者)對(duì)象加入到當(dāng)前屬性的依賴中。 -
當(dāng)數(shù)據(jù)發(fā)生變化時(shí),Vue3 會(huì)通過監(jiān)聽器檢測(cè)到變化,并觸發(fā)對(duì)應(yīng)數(shù)據(jù)的
set
操作,代理對(duì)象handler.set()
會(huì)被調(diào)用,從而通知該屬性下所有依賴的 ‘Watcher’ 對(duì)象更新; -
Watcher
對(duì)象被通知后,會(huì)向?qū)?yīng)的組件發(fā)送消息通知需要重新渲染視圖,從而實(shí)現(xiàn)整個(gè)頁面的更新。
Vue3 中使用 Proxy 對(duì)象實(shí)現(xiàn)數(shù)據(jù)響應(yīng)式的代碼如下:
const data = { msg: 'Hello Vue' }
const reactiveData = new Proxy(data, {
get(target, key) {
console.log('get');
return target[key];
},
set(target, key, value) {
console.log('set');
target[key] = value;
return true;
}
})
上述代碼中,data
對(duì)象通過 Proxy 對(duì)象 reactiveData
進(jìn)行代理,當(dāng)訪問 reactiveData
對(duì)象的屬性時(shí),Proxy 對(duì)象內(nèi)部的 get() 函數(shù)被調(diào)用;當(dāng)設(shè)置屬性時(shí),Proxy 對(duì)象內(nèi)部的 set() 函數(shù)被調(diào)用。在 get() 和 set() 函數(shù)中,可以對(duì)屬性的讀取和賦值進(jìn)行攔截,從而實(shí)現(xiàn)數(shù)據(jù)的響應(yīng)式。
Proxy詳解
Proxy 是在 ES6 中新增的一個(gè)對(duì)象,用于代理另一個(gè)對(duì)象并攔截該對(duì)象的讀取、賦值、屬性定義等一系列操作,其語法如下:
new Proxy(target, handler)
Proxy中的參數(shù):文章來源:http://www.zghlxwxcb.cn/news/detail-476963.html
- target:被代理的目標(biāo)對(duì)象。
- handler:一個(gè)對(duì)象,其屬性是鉤子函數(shù)(trap),用于攔截代理對(duì)象的操作。
handler 包含以下可選鉤子函數(shù)(trap):文章來源地址http://www.zghlxwxcb.cn/news/detail-476963.html
- get(target, prop):用于攔截對(duì)象的讀取操作。
- set(target, prop, value):用于攔截對(duì)象的賦值操作。
- has(target, prop):用于攔截 in 操作。
- deleteProperty(target, prop):用于攔截 delete 操作。
- apply(target, thisArg, args):用于攔截函數(shù)調(diào)用。
- construct(target, args):用于攔截 new 操作。
Proxy的優(yōu)點(diǎn)
-
Proxy
可以直接監(jiān)聽對(duì)象而非屬性; -
Proxy
可以直接監(jiān)聽數(shù)組的變化; -
Proxy
返回的是一個(gè)新對(duì)象,我們可以只操作新的對(duì)象達(dá)到目的,而Object.defineProperty
只能遍歷對(duì)象屬性直接修改;
到了這里,關(guān)于Vue2和Vue3響應(yīng)式原理實(shí)現(xiàn)的核心的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!