vue3.0 Reactive數(shù)據(jù)更新頁面沒有刷新的問題
vue3.0 Reactive數(shù)據(jù)更新頁面沒有刷新
vue 3.0 ref 和 Reactive 數(shù)據(jù)響應式,以及使用 Reactive 數(shù)據(jù)已更新但頁面沒有同步刷新異常
Vue 3.0 中我們使用 reactive() 定義的響應式數(shù)據(jù)的時候,當我們對象再次賦值,我們發(fā)現(xiàn)數(shù)據(jù)已經(jīng)修改成功,但是頁?并沒有自動渲染成最新的數(shù)據(jù);
這時我們可以改成 ref () 或者對 reactive() 綁定的數(shù)據(jù)類型下點功夫;
- ref()
ref() 接受一個內(nèi)部值并返回一個響應式且可變的 ref 對象。ref 對象僅有一個 .value property,指向該內(nèi)部值
<template>
? <div>
? ? <button @click="changeMsg">更改數(shù)據(jù)</button>
? ? <div>{{ message }}</div>
? </div>
</template>
<script setup lang="ts">
import {ref} from 'vue'
/**
?* ? ref() 基礎用法
?*/
?
let message = ref<string | number>("測試數(shù)據(jù)")
/**
?* ? 更改 ref 數(shù)據(jù)
?*/
??
const changeMsg = () => {
? ?message.value = "更改測試數(shù)據(jù)"
}
</script>- reactive()
reactive() 主要時用來綁定一些復雜的數(shù)據(jù)類型,比如(對象、數(shù)組) ;它不可以綁定普通的數(shù)據(jù)類型,否則會報錯;如果我們需要綁定普通的數(shù)據(jù)類型,建議使用上面的 ref()
<template>
? <div>
? ? <button @click="changeObj">更改數(shù)據(jù)</button>
? ? <div> {{obj.data}} </div>
? ? <div> {{obj.dataBoolean}} </div>
? ? <div> {{obj.dataArr}} </div>
? </div>
</template>
<script setup lang="ts">
import {reactive} from 'vue'
/**
?* ? reactive() 基礎用法
?*/
?
const obj = reactive({
? ? data: '',
? ? dataBoolean: false,
? ? dataArr: <number[]>[],
})
/**
?* ? 更改 reactive() 數(shù)據(jù)
?*/
?const changeObj = () => {
? ? ?obj .data = '測試數(shù)據(jù)'
? ? ?obj .dataBoolean = true
? ? ?obj .dataArr = [1, 2, 3, 4, 5, 6]
?}
</script>vue3.0中的reactive用法
reactive 是 Vue3 中提供的實現(xiàn)響應式數(shù)據(jù)的方法。
在 Vue2 中響應式數(shù)據(jù)是通過 defineProperty 來實現(xiàn)的,
在 Vue3 中響應式數(shù)據(jù)是通過 ES6 的 Proxy來實現(xiàn)的。
reactive 參數(shù)必須是對象 (json / arr)
如果給 reactive 傳遞了其它對象
- 默認情況下,修改對象無法實現(xiàn)界面的數(shù)據(jù)綁定更新。
- 如果需要更新,需要進行重新賦值。(即不允許直接操作數(shù)據(jù),需要放個新的數(shù)據(jù)來替代原數(shù)據(jù))
在 reactive 使用基本類型參數(shù)
基本類型(數(shù)字、字符串、布爾值)在 reactive 中無法被創(chuàng)建成 proxy 對象,也就無法實現(xiàn)監(jiān)聽。
<template>
<div>
<p>{{msg}}</p>
<button @click="c">button</button>
</div>
</template>
<script>
import { reactive } from 'vue'
export default {
name: 'App',
setup() {
let msg = reactive(0)
function c() {
console.log(msg);
msg ++;
}
return {
msg,
c
};
}
}
</script>
點擊 button ,我們期望的結果是數(shù)字從 0 變成 1,然而實際上界面上的數(shù)字并沒有發(fā)生任何改變。
查看控制臺,它的輸出是這樣的(我點了 3 次)

出現(xiàn)提示
value cannot be made reactive: 0
而輸出的值確實發(fā)生了變化,只不過這種變化并沒有反饋到界面上,也就是說并沒有實現(xiàn)雙向數(shù)據(jù)綁定。當然,如果是 ref 的話,就不存在這樣的問題。而如果要使用 reactive ,我們需要將參數(shù)從 基本類型 轉化為 對象。
<template>
<div>
<p>{{msg.num}}</p>
<button @click="c">button</button>
</div>
</template>
<script>
import { reactive } from 'vue'
export default {
name: 'App',
setup() {
let msg = reactive({
num: 0
})
function c() {
console.log(msg);
msg.num ++;
}
return {
msg,
c
};
}
}
</script>將參數(shù)替換成了對象 {num: 0},此時,點擊按鈕界面就會產(chǎn)生改變(我點了 3 次)。

在控制臺打印消息

可以看到,msg 成功被創(chuàng)建成了 proxy 對象,他通過劫持對象的 get 和 set 方法實現(xiàn)了對象的雙向數(shù)據(jù)綁定。
深層的、對象內(nèi)部的變化也能被察覺到(注意下面代碼中的 inner )
<template>
<div>
<p>{{msg.num.inner}}</p>
<button @click="c">button</button>
</div>
</template>
<script>
import { reactive } from 'vue'
export default {
name: 'App',
setup() {
let msg = reactive({
num: {
inner: 0
}
})
function c() {
console.log(msg);
msg.num.inner ++;
}
return {
msg,
c
};
}
}
</script>
數(shù)組變化也不在話下。
<template>
<div>
<p>{{msg}}</p>
<button @click="c">button</button>
</div>
</template>
<script>
import { reactive } from 'vue'
export default {
name: 'App',
setup() {
let msg = reactive([1, 2, 3])
function c() {
console.log(msg);
msg[0] += 1;
msg[1] = 5;
}
return {
msg,
c
};
}
}
</script>
在-reactive-使用-date-參數(shù)在 reactive 使用 Date 參數(shù)
如果參數(shù)不是數(shù)組、對象,而是稍微奇怪一點的數(shù)據(jù)類型,例如說 Date ,那么麻煩又來了。
<template>
<div>
<p>{{msg}}</p>
<button @click="c">button</button>
</div>
</template>
<script>
import { reactive } from 'vue'
export default {
name: 'App',
setup() {
let msg = reactive(new Date())
function c() {
console.log(msg);
msg.setDate(msg.getDate() + 1);
console.log(msg);
}
return {
msg,
c
};
}
}
</script>!
這里我先打印了 msg 兩次,可以看到,點擊一次 button ,msg 的數(shù)據(jù)是存在變化的,但界面并未發(fā)生變化,同時我們發(fā)現(xiàn)在控制臺里,msg 并未被識別成 proxy。
就算我們把 Date 放在對象里,就像這樣
<template>
<div>
<p>{{msg.date}}</p>
<button @click="c">button</button>
</div>
</template>
<script>
import { reactive } from 'vue'
export default {
name: 'App',
setup() {
let msg = reactive({
date: new Date()
});
function c() {
console.log(msg);
msg.date.setDate(msg.date.getDate() + 1);
console.log(msg);
}
return {
msg,
c
};
}
}
</script>也仍然不起效果。


顯然,對于這種數(shù)據(jù)類型,我們需要做特殊處理。
這個特殊處理就是重新賦值(,而不是直接修改原來的值)。
<template>
<div>
<p>{{msg.date}}</p>
<button @click="c">button</button>
</div>
</template>
<script>
import { reactive } from 'vue'
export default {
name: 'App',
setup() {
let msg = reactive({
date: new Date()
});
function c() {
console.log(msg);
msg.date.setDate((msg.date.getDate() + 1));
msg.date = new Date(msg.date);
console.log(msg);
}
return {
msg,
c
};
}
}
</script>這里我采用了拷貝的方案重新賦值了 msg.date,界面成功發(fā)生了變化(日期 + 1)。

響應式代理 vs. 原始對象
值得注意的是,reactive() 返回的是一個源對象的 Proxy,它和源對象是不相等的:
const raw = {}
const proxy = reactive(raw)
// 代理和原始對象不是全等的
console.log(proxy === raw) // false只有代理是響應式的,更改原始的對象不會觸發(fā)更新。因此,使用 Vue 的響應式系統(tǒng)的最佳實踐是 僅使用代理作為狀態(tài)。
為保證訪問代理的一致性,對同一個對象調用 reactive() 會總是返回同樣的代理,而對代理調用 reactive() 則會返回它自己:
// 在同一個對象上調用 reactive() 會返回相同的代理 console.log(reactive(raw) === proxy) // true // 在一個代理上調用 reactive() 會返回它自己 console.log(reactive(proxy) === proxy) // true
這個規(guī)則對深層級的對象也適用。依靠深層響應性,響應式對象內(nèi)的深層級對象依然是代理:
const proxy = reactive({})
const raw = {}
proxy.nested = raw
console.log(proxy.nested === raw) // false總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
vue在html標簽{{}}中調用函數(shù)的方法總結及對比
這篇文章主要給大家介紹了關于vue在html標簽{{}}中調用函數(shù)的方法總結及對比,文中通過實例代碼介紹的非常詳細,對大家學習或者使用vue具有一定的參考學習價值,需要的朋友可以參考下2023-03-03
antd form表單使用setFildesValue 賦值失效的解決
這篇文章主要介紹了antd form表單使用setFildesValue 賦值失效的解決方案,具有很好的參考價值,希望對大家有所幫助。2023-04-04
vue中{__ob__: observer}對象轉化為數(shù)組進行遍歷方式
這篇文章主要介紹了vue中{__ob__: observer}對象轉化為數(shù)組進行遍歷方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10

