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

Vue3和Vue2的響應(yīng)式原理

 更新時間:2023年05月31日 11:39:04   作者:書源  
這篇文章我們將探討Vue3框架的優(yōu)秀特性、使用原理、周邊生態(tài)和實戰(zhàn)應(yīng)用,系統(tǒng)的學(xué)習(xí)Vue生態(tài)體系,希望和大家共同成長,我們一起探討下Vue3和Vue2的響應(yīng)式原理,那究竟什么是“響應(yīng)式”,接下來跟著小編一起來學(xué)習(xí)吧

什么是響應(yīng)式?

簡單來說,響應(yīng)式就是頁面的模版內(nèi)容能隨著數(shù)據(jù)變化而重新渲染。我們來看一個案例:

<template>
  <div id="app">
    <div>Count: {{ count }}</div>
    <button class="btn" @click="onAdd">Add</button>
  </div>
</template>
<script setup>
import { ref } from "vue";
const count = ref(1);
const onAdd = () => {
  count.value++;
};
</script>

在這段代碼中,ref 是 Vue3 官方提供的響應(yīng)式 API,count 就是通過響應(yīng)式 API 聲明的響應(yīng)式數(shù)據(jù)。count 這個數(shù)據(jù)可以直接在模板里使用,例如上述代碼中我們使用了count 數(shù)據(jù)進(jìn)行顯示。

那么響應(yīng)式體現(xiàn)在哪呢?上述代碼有一個點擊事件的函數(shù) onAdd,這個函數(shù)實現(xiàn)了對 count 數(shù)值的自增操作。每當(dāng)點擊這個 onAdd 事件,count 就會自動加 1,對應(yīng)使用到 count 的模板也會隨之重新渲染最新的數(shù)據(jù)。

上述功能代碼里的這種視圖隨著數(shù)據(jù)的變化,就是響應(yīng)式的特征?;?Vue的響應(yīng)式 API 生成的數(shù)據(jù),就是響應(yīng)式數(shù)據(jù),如果響應(yīng)式數(shù)據(jù)發(fā)生了變化,那么依賴了數(shù)據(jù)的視圖也會跟著變化。

那響應(yīng)式原理是如何實現(xiàn)的呢?接下來我們就一起來看下。

響應(yīng)式原理

我們以一個經(jīng)常被拿來當(dāng)作典型例子的用例即是 Excel 表格:

這里單元格 A2 中的值是通過公式 = 5 * A1 來定義的 ,我們期望更改 A1, A2 也隨即自動更新。

而 JavaScript 默認(rèn)并不是這樣的。如果我們用 JavaScript 寫類似的邏輯:

let A1 = 1;
let A2 = 5 * A1;
console.log(A2); // 5A1 = 2;console.log(A2); // 仍然是 5

我們現(xiàn)在的目標(biāo)是,在 A1 變化時會調(diào)用 effect() (產(chǎn)生作用)。在具體實現(xiàn)時,Vue2和Vue3采取了不同的實現(xiàn)方案,我們一一看下【備注:更完善的響應(yīng)式原理會在專欄后續(xù)補(bǔ)充】。

Vue2響應(yīng)式方案

Vue2的實現(xiàn)方案主要是借助于Object.defineProperty。

這里來看下如下通過Object.defineProperty ,來實現(xiàn)我們的目標(biāo):

let obj = {};
let A1;
let A2;
function effect() {
  A2 = 5 * A1;
}
Object.defineProperty(obj, "A1", {
  get() {
    return A1;
  },
  set(val) {
    A1 = val;
    effect();
  },
});
obj.A1 = 1;
console.log(A2); // 打印5obj.A1 = 2;console.log(A2); // 打印10

在上面的實現(xiàn)中,我們定義個一個對象 obj,使用 Object.defineProperty 代理 A1  屬性,進(jìn)而對 obj 對象的 value 屬性實現(xiàn)了攔截,讀取 A1 屬性的時候執(zhí)行 get 函數(shù),修改 A1 屬性的時候執(zhí)行 set 函數(shù),在 set 函數(shù)內(nèi)部調(diào)用 effect() 函數(shù),從而實現(xiàn)響應(yīng)式。

接下來我們來看下Vue3的響應(yīng)式方案,不過它分非原始值的響應(yīng)式和原始值的響應(yīng)式。

非原始值的響應(yīng)式方案

什么是非原始值呢?其實就是對象,而并非數(shù)字、字符串。

非原始值的響應(yīng)式數(shù)據(jù)是基于Proxy實現(xiàn)的,它允許我們攔截并重新定義一個對象的基本操作,具體API 我們可以訪問MDN 文檔。

這里來看下如下通過Proxy ,來實現(xiàn)我們的目標(biāo):

let obj = {};
let A1;
let A2;
function effect(val) {
  A2 = 5 * val;
}
let proxy = new Proxy(obj, {
  get: function (target, prop) {
    return target[prop];
  },
  set: function (target, prop, value) {
    target[prop] = value;
    effect(value);
  },
});
proxy.A1 = 1;
console.log(A2); // 打印5proxy.A1 = 2;console.log(A2); // 打印10

在上面的實現(xiàn)中,我們定義了一個對象 obj,使用 Proxy 代理 obj,實現(xiàn)了和Vue2相同的功能 ,讀取 A1 屬性的時候執(zhí)行 get 函數(shù),修改 A1 屬性的時候執(zhí)行 set 函數(shù),在 set 函數(shù)內(nèi)部調(diào)用 effect() 函數(shù),從而實現(xiàn)響應(yīng)式。

Object.defineProperty所不同的是Proxy 是針對對象來監(jiān)聽,而不是針對某個具體屬性,所以不僅可以代理那些定義時不存在的屬性,還可以代理更豐富的數(shù)據(jù)結(jié)構(gòu),比如 Map、Set 等等。

原始值的響應(yīng)式方案

什么是原始值?原始值指的是Boolean、Number、String、null等類型的值。

在JavaScript中,原始值是按值傳遞的,而非按引用傳遞。如果一個函數(shù)接收原始值作為參數(shù),那么形參和實參之間沒有引用關(guān)系,是兩個完全獨立的值。此外,JavaScript中的proxy無法提供對原始值的代理,想要將原始值變成響應(yīng)式數(shù)據(jù),就必須對其做一層包裹,借助對象的 get 和 set 函數(shù)來實現(xiàn):

let A1 = 1;
let A2;
function effect(val) {
  A2 = 5 * val;
}
let obj = {
  get value() {
    return A1;
  },
  set value(val) {
    A1 = val;
    effect(val);
  },
};
obj.value = 1;
console.log(A2); // 打印5obj.value = 2;console.log(A2); // 打印10

在上面的實現(xiàn)中,我們利用對象的 get 和 set 函數(shù)來進(jìn)行監(jiān)聽,這種響應(yīng)式的實現(xiàn)方式,只能攔截某一個屬性,這也是 Vue 3 中 ref 這個 API 的實現(xiàn)。

以上我們了解了響應(yīng)式原理,不過我們想在工作中更好地運用響應(yīng)式API,我們還需要知道在響應(yīng)式開發(fā)中可能會遇到什么“坑”。

響應(yīng)式原理注意事項

我們先來了解一下 Vue 2的注意事項,由于 JavaScript 的限制,Vue 不能檢測數(shù)組和對象的變化。盡管如此我們還是有一些辦法來回避這些限制并保證它們的響應(yīng)性。

Vue 2注意事項

對于對象,Vue2 無法檢測 property 的添加或移除。由于 Vue 會在初始化實例時對 property 執(zhí)行 getter/setter 轉(zhuǎn)化,所以 property 必須在 data 對象上存在才能讓 Vue 將它轉(zhuǎn)換為響應(yīng)式的。例如:

var vm = new Vue({ data: { a: 1 } }); // `vm.a` 是響應(yīng)式的vm.b = 2// `vm.b` 是非響應(yīng)式的

對于已經(jīng)創(chuàng)建的實例,Vue 不允許動態(tài)添加根級別的響應(yīng)式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套對象添加響應(yīng)式 property。例如:

Vue.set(vm.someObject, "b", 2);

您還可以使用 vm.$set 實例方法,這也是全局 Vue.set 方法的別名:

this.$set(this.someObject, "b", 2);

對于數(shù)組,Vue2 不能檢測以下數(shù)組的變動:

  • 當(dāng)你利用索引直接設(shè)置一個數(shù)組項時,例如:vm.items[index] = newValue
  • 當(dāng)你修改數(shù)組的長度時,例如:vm.items.length = newLength

舉個例子:

var vm = new Vue({ 
	data: {
		items: ["a", "b", "c"]
	} 
});
vm.items[1] = "x"; // 不是響應(yīng)性的vm.items.length = 2 // 不是響應(yīng)性的

為了解決第一類問題,以下方式都可以實現(xiàn)和 vm.items[indexOfItem] = newValue 相同的效果,同時也將在響應(yīng)式系統(tǒng)內(nèi)觸發(fā)狀態(tài)更新:

// Vue.setVue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splicevm.items.splice(indexOfItem, 1, newValue)
// 該方法是全局方法 Vue.set 的一個別名
vm.$set(vm.items, indexOfItem, newValue);

為了解決第二類問題,你可以使用 splice

vm.items.splice(newLength);

Vue 3注意事項

Vue.js 3 的響應(yīng)式開發(fā)有什么需要注意的?

第一個注意事項是響應(yīng)式數(shù)據(jù)解構(gòu),這可能會丟失響應(yīng)式聯(lián)系,例如:

<template>
  <div id="app">
    <input v-model="text" placeholder="文本信息" /> 文本信息:{{ text }}
  </div>
</template>
<script setup>
import { reactive } from "vue";
const state = reactive({ text: "hello world" });
const { text } = state;
</script>

在上述代碼中,text 的響應(yīng)式聯(lián)系并不會生效,修改 text 內(nèi)容后,不會觸發(fā)頁面的展示文本 text 的視圖更新渲染。這是為什么呢?

這里我們用 reactive 定義了 state 響應(yīng)式數(shù)據(jù),但是在之后又把其中的 state.text 解構(gòu)賦值給了變量 text,這就會斷掉響應(yīng)式聯(lián)系,導(dǎo)致再怎么更新 text 都不會觸發(fā)視圖重新更新渲染。

那如果我們就想用解構(gòu)的方法來使用text變量怎么辦?可以借助toRefs 來實現(xiàn):

<script setup>
import { reactive, toRefs } from "vue";
const state = reactive({ text: "hello world" });
const { text } = toRefs(state);
</script>

第二個注意事項是Vue3官方指明謹(jǐn)慎使用的API,例如 shallowReactive 、 shallowReadonly等等,示例:

const state = shallowReactive({
  foo: 1,
  nested: {
    bar: 2
  }
})
// 更改狀態(tài)自身的屬性是響應(yīng)式的
state.foo++
// ...但下層嵌套對象不會被轉(zhuǎn)為響應(yīng)式
isReactive(state.nested) // false
// 不是響應(yīng)式的
state.nested.bar++

異步更新隊列

異步隊列更新,這是Vue2和Vue3都共存的注意事項,當(dāng)你在 Vue 中更改響應(yīng)式狀態(tài)時,最終的 DOM 更新并不是同步生效的,而是由 Vue 將它們緩存在一個隊列中,直到下一個“tick”才一起執(zhí)行。這樣是為了確保每個組件無論發(fā)生多少狀態(tài)改變,都僅執(zhí)行一次更新。

多數(shù)情況我們不需要關(guān)心這個過程,但是如果你想基于更新后的 DOM 狀態(tài)來做點什么,這就可能會有些棘手。雖然 Vue.js 通常鼓勵開發(fā)人員使用數(shù)據(jù)驅(qū)動的方式思考,避免直接接觸 DOM,但是有時我們必須要這么做。

nextTick() 可以在狀態(tài)改變后立即使用,以等待 DOM 更新完成。你可以傳遞一個回調(diào)函數(shù)作為參數(shù),或者 await 返回的 Promise。示例:

<script setup>
import { ref, nextTick } from 'vue'
const count = ref(0)
async function increment() {
  count.value++
  // DOM 還未更新
  console.log(document.getElementById('counter').textContent) // 0
  await nextTick()
  // DOM 此時已經(jīng)更新
  console.log(document.getElementById('counter').textContent) // 1
}
</script>
<template>
  <button id="counter" @click="increment">{{ count }}</button>
</template>

總結(jié)

今天的知識點我們來做個總結(jié):

1、我們認(rèn)識了什么是響應(yīng)式,其實就是頁面的模版內(nèi)容能隨著數(shù)據(jù)變化而重新渲染。

2、我們總結(jié)了Vue2和Vue3各自的響應(yīng)式實現(xiàn)原理以及開發(fā)需要注意的事項。

以上就是Vue3和Vue2的響應(yīng)式原理的詳細(xì)內(nèi)容,更多關(guān)于Vue3和Vue2 響應(yīng)式原理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue實現(xiàn)父子組件頁面刷新的幾種常用方法

    Vue實現(xiàn)父子組件頁面刷新的幾種常用方法

    很多時候我們在操作過頁面時候,特別是增刪改操作之后,數(shù)據(jù)會有所改變,本文主要介紹了Vue實現(xiàn)父子組件頁面刷新的幾種常用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • 從零開始實現(xiàn)Vue簡單的Toast插件

    從零開始實現(xiàn)Vue簡單的Toast插件

    這篇文章主要給大家介紹了如何從零開始實現(xiàn)Vue簡單的Toast插件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • 詳解Vue.js中的組件傳值機(jī)制

    詳解Vue.js中的組件傳值機(jī)制

    Vue.js 是一款流行的前端框架,它提供了一些方便的機(jī)制來管理組件之間的通信,其中包括組件傳值,本文將詳細(xì)介紹 Vue.js 中的組件傳值機(jī)制,包括父子組件傳值、兄弟組件傳值、跨級組件傳值等多種方式,需要的朋友可以參考下
    2023-08-08
  • vue使用xlsx庫和xlsx-style庫導(dǎo)入導(dǎo)出excel、設(shè)置單元格背景色、文字居中、合并單元格、設(shè)置列寬

    vue使用xlsx庫和xlsx-style庫導(dǎo)入導(dǎo)出excel、設(shè)置單元格背景色、文字居中、合并單元格、設(shè)置列寬

    xlsx是由SheetJS開發(fā)的一個處理excel文件的npm庫,適用于前端開發(fā)者實現(xiàn)導(dǎo)入導(dǎo)出excel文件的經(jīng)典需求,這篇文章主要介紹了vue使用xlsx庫和xlsx-style庫導(dǎo)入導(dǎo)出excel、設(shè)置單元格背景色、文字居中、合并單元格、設(shè)置列寬,需要的朋友可以參考下
    2023-11-11
  • vue中路由跳轉(zhuǎn)不計入history的操作

    vue中路由跳轉(zhuǎn)不計入history的操作

    這篇文章主要介紹了vue中路由跳轉(zhuǎn)不計入history的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • vue界面發(fā)送表情的實現(xiàn)代碼

    vue界面發(fā)送表情的實現(xiàn)代碼

    這篇文章主要介紹了vue界面發(fā)送表情的實現(xiàn)代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 淺析為什么Vue使用虛擬DOM

    淺析為什么Vue使用虛擬DOM

    Vue?使用虛擬?DOM?的初衷不僅是為了性能優(yōu)化,更重要的是為了解決開發(fā)效率和靈活性的問題,下面我們就來探討一下虛擬DOM的作用與原理吧
    2024-12-12
  • vue.js 實現(xiàn)v-model與{{}}指令方法

    vue.js 實現(xiàn)v-model與{{}}指令方法

    這篇文章主要介紹了vue.js 實現(xiàn)v-model與{{}}指令方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-10-10
  • vue請求接口并且攜帶token的實現(xiàn)

    vue請求接口并且攜帶token的實現(xiàn)

    本文主要介紹了vue請求接口并且攜帶token的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Vue3非遞歸渲染Tree組件的初步實現(xiàn)代碼

    Vue3非遞歸渲染Tree組件的初步實現(xiàn)代碼

    這篇文章主要介紹了Vue3非遞歸渲染Tree組件的初步實現(xiàn),文中通過代碼示例講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定幫助,需要的朋友可以參考下
    2024-05-05

最新評論

交城县| 丘北县| 镇安县| 安宁市| 隆回县| 锡林郭勒盟| 耿马| 阳曲县| 双城市| 子洲县| 吉林省| 娄烦县| 科技| 库伦旗| 鹤山市| 板桥市| 湄潭县| 乾安县| 卓尼县| 扶风县| 南康市| 新乐市| 利川市| 马鞍山市| 河曲县| 太白县| 普兰店市| 新建县| 灵寿县| 武汉市| 绥江县| 搜索| 皋兰县| 涞源县| 南皮县| 波密县| 乌海市| 荔波县| 蒲城县| 宜兰市| 东乡族自治县|