問題:
在uniapp-vue3的專案中,使用reactive定義了一個陣列,之後使用foreach對item的某個屬性進行重新賦值,但經過console資料顯示已經賦上值了,但是檢視一直不更新,包括嘗試nextTick(()=>{})和internalInstance.ctx.$forceUpdate()方法都無效。
分析:
檢視了官網文件,發現了這裡(響應式基礎 | Vue.js (vuejs.org)),注意第二條
reactive函式會返回一個Proxy
包裝的物件,所以直接賦值一個陣列時會使定義的變數失去響應式。
let userInfo = reactive([{name:'hanmeimei',age:12}]) console.log(userInfo) // Proxy(Array) 列印出來是一個Proxy物件 當然具備響應式 userInfo =[{name:'zhangsan',age:18},{name:'lisi,age:10}]// 直接後端資料進行賦值 console.log(userInfo) //[{name:'zhangsan',age:18},{name:'lisi,age:10}] 可以看出 就是列印出了一個普通的陣列 所以不具備響應式
所以對於reactive
建立的響應式資料應該避免直接使用=
號進行賦值;會覆蓋響應式;
解決方案:
1、在封裝一層資料,例如:
<script setup> import { reactive, ref } from "vue"; // 定義響應式 let choosenList = reactive({list:[]}); // 請求的資料 let newList1 = [ { name: "Eula", age: "18", isActive: false }, { name: "Umbra", age: "17", isActive: false }, ] // 更改資料 const setList = () => { choosenList.list= newList1 } </script>
2、使用陣列的splice
來直接更改原陣列
還是用reactive
來定義響應式資料,只不過改資料的方式變了,使用陣列的原生方法splice()
來更改原陣列,不是直接覆蓋所以並不會影響響應式;
可改變原陣列的原生方法還有push、unshift、pop、shift、reverse、sort、splice、fill
<script setup> import { reactive, ref } from "vue"; // 定義響應式 let list1 = reactive([]); // 請求的資料 let newList1 = [ { name: "Eula", age: "18", isActive: false }, { name: "Umbra", age: "17", isActive: false }, ] // 更改資料 const setList1 = () => { // splice三個引數時 第一項是起始索引 第二項是長度 第三項是新插入的元素,可以有多個 list1.splice(0,list1.length,...newList1) } </script>
3、使用 ref 來定義資料
複雜資料型別也可以使用ref
進行定義,而且資料都是響應式的;原理就有點像第一種方式,重新包裝了一層value;每次使用的時候都要寫.value
;
ref實際就是對一個普通值做了一層包裝,包裝成一個物件,並透過其get和set實現依賴收集和更新,其實現原理類似於computed;
<script setup> import { reactive, ref } from "vue"; // 定義響應式 let list1 = ref([]); // 請求的資料 let newList1 = [ { name: "Eula", age: "18", isActive: false }, { name: "Umbra", age: "17", isActive: false }, ] // 更改資料 const setList1 = () => { list1.value = newList1; } </script>
let userInfo =reactive([{name:'Eula'}])