Vue不能檢測(cè)到數(shù)據(jù)變化的幾種情況說(shuō)明
Vue不能檢測(cè)到數(shù)據(jù)變化的情況
Vue 實(shí)現(xiàn)了數(shù)據(jù)的雙向綁定,所以我們?cè)诟臄?shù)據(jù)時(shí),頁(yè)面就會(huì)實(shí)時(shí)的反映出修改的變化
但是由于javascript 的限制,有幾種情況,vue是不能檢測(cè)到數(shù)據(jù)變化的
第一類:對(duì)于數(shù)組
1. 當(dāng)你利用索引直接設(shè)置一個(gè)項(xiàng)時(shí),例如:
vm.items[indexOfItem] = newValue
2. 當(dāng)你修改數(shù)組的長(zhǎng)度時(shí),例如:
vm.items.length = newLength
如下例
?? ?new Vue({ ?? ??? ?data(){ ?? ??? ??? ?return { ?? ??? ??? ??? ?arr:[ ?? ??? ??? ??? ??? ?{id:1,name:"haha",age:18}, ?? ??? ??? ??? ??? ?{id:2,name:"hehe",age:19} ?? ??? ??? ??? ?] ?? ??? ??? ?} ?? ??? ?} ?? ?}) ?? ?...... ?? ?methods:{ ?? ??? ?change(){ ?? ??? ??? ?this.arr[0] = {id:1,name:"gege",age:30}; ?//這種寫法vue是不能檢測(cè)到的, 也就是說(shuō)頁(yè)面的數(shù)據(jù)不會(huì)改變 ?? ??? ??? ?this.arr[0].name = "gege"; ?? ??? ??? ?this.arr[0].age = 30; ? //這種方式是可以檢測(cè)到的, 這是更改的數(shù)組內(nèi)部的對(duì)象的屬性是可以檢測(cè)到變化的 ?? ??? ??? ?//也可以使用 vue 提供的方法 ?? ??? ??? ?this.$set(this.arr,0,{id:1,name:"gege",age:30}) ; //這種方法也是可以的 ?? ??? ??? ?//還可以使用 vue 的變種函數(shù) ?? ??? ??? ?this.arr.splice(0,1,{id:1,name:"gege",age:30}); ?? ??? ??? ?//這里的 splice方法其實(shí)已經(jīng)不是 js 的 splice方法了, 它是被vue 改寫過(guò)的方法 ?? ??? ?} ?? ?}
從上面我們可以看到,如果想要通過(guò)數(shù)組下標(biāo)修改數(shù)組的話,vue 是檢測(cè)不到數(shù)據(jù)的變化的,要么使用 $set , splice 等數(shù)組的方法,要么就再向組數(shù)內(nèi)部走一級(jí),直接修改內(nèi)部對(duì)象的屬性也是可以的
第二類:對(duì)于對(duì)象
vue 是可以檢測(cè)到對(duì)象中數(shù)據(jù)發(fā)生的改動(dòng)的,因?yàn)槌跏蓟臅r(shí)候 對(duì)象的每一個(gè)屬性 都生成好了 getter 和setter方法,但是我們?nèi)绻诔绦蜻\(yùn)行過(guò)程中 動(dòng)態(tài)的給對(duì)象添加新的屬性,刪除屬性,vue 是檢測(cè)不到的
?? ?new Vue({ ?? ??? ?data(){ ?? ??? ??? ?return { ?? ??? ??? ??? ?a:{ ?? ??? ??? ??? ??? ?b:"c" ?? ??? ??? ??? ?} ?? ??? ??? ?} ?? ??? ?} ?? ??? ?...... ?? ??? ?mehtods:{ ?? ??? ??? ?changes(){ ?? ??? ??? ??? ?this.a.bb = "bbbb"; //這種寫法是在 a 對(duì)象上面添加了一個(gè) bb 的屬性, vue 是檢測(cè)不到的 ?? ??? ??? ??? ?//所以這種情況下, 我們要使用 $set? ?? ??? ??? ??? ?this.$set(this.a,"bb","bbbbb"); ?//這樣就可以解決問(wèn)題,? ?? ??? ??? ?} ?? ??? ?} ?? ?})
上面只寫了添加對(duì)象屬性時(shí)的情況,刪除對(duì)象的屬性時(shí),1.也可使用 $set
有時(shí)你可能需要為已有對(duì)象賦予多個(gè)新屬性,比如使用 Object.assign() 或 _.extend()。在這種情況下,你應(yīng)該用兩個(gè)對(duì)象的屬性創(chuàng)建一個(gè)新的對(duì)象。所以,如果你想添加新的響應(yīng)式屬性,不要像這樣:
Object.assign(vm.userProfile, { age: 27, favoriteColor: ‘Vue Green' })
你應(yīng)該這樣做:
vm.userProfile = Object.assign({}, vm.userProfile, { age: 27, favoriteColor: ‘Vue Green' })
Vue檢測(cè)數(shù)據(jù)的原理
一個(gè)簡(jiǎn)單的例子,總結(jié)一下vue監(jiān)測(cè)數(shù)據(jù)
<div id="app"> <h1>學(xué)生信息</h1> <button @click="addSex">添加sex屬性,默認(rèn)值為男</button> <button @click="changeSex">修改sex屬性</button> <button @click="unshiftFriend">在列表首位添加一個(gè)朋友</button> <button @click="changeFriendName">修改第一個(gè)朋友的名字為:張三</button> <button @click="addHobby">添加一個(gè)愛(ài)好</button> <button @click="changeHobby">修改第一個(gè)愛(ài)好為:開(kāi)車</button> <h2>姓名:{{student.name}}</h2> <h2>性別:{{student.sex}}</h2> <h2>愛(ài)好:</h2> <ul> <li v-for="(h,index) in student.hobby" :key="index">{{h}}</li> </ul> <h2>朋友們:</h2> <ul> <li v-for="(f,index) in student.friends" :key="index">{{f.name}} -- {{f.age}}</li> </ul> </div>
const app = new Vue({ el: "#app", data: { student: { name: "AIpoem", hobby: ["抽煙","喝酒","燙頭"], friends: [ {name: "jerry",age: 18}, {name: "Cici",age:19} ] } }, methods: { addSex() { // this.student.sex = "男" 不是響應(yīng)式 this.$set(this.student,"sex","男"); }, changeSex() { // 直接改即可,因?yàn)樯厦嫣砑拥膕ex屬性為響應(yīng)式 this.student.sex='女' }, unshiftFriend() { this.student.friends.unshift({name:"newFriend",age:20}); }, changeFriendName() { // 這里直接改即可,name屬性是響應(yīng)式的 this.student.friends[0].name = "張三"; }, addHobby() { this.student.hobby.push("新愛(ài)好"); }, changeHobby() { // this.student.hobby[0] = "開(kāi)車" 不是響應(yīng)式 this.student.hobby.splice(0,1,"開(kāi)車"); } } })
關(guān)于vue監(jiān)視對(duì)象:
直接添加的sex屬性,沒(méi)有g(shù)etter和setter,無(wú)法實(shí)現(xiàn)響應(yīng)式
利用Vue.set()添加的sex屬性,有g(shù)etter和setter,可以實(shí)現(xiàn)響應(yīng)式
另一種寫法,和上面作用一樣
關(guān)于vue監(jiān)視數(shù)組:
比如這個(gè)例子,一開(kāi)始頁(yè)面是抽煙和喝酒,button綁定的點(diǎn)擊事件中的語(yǔ)句是this.student.hobby[0] = "學(xué)習(xí)";,之后再輸出app.student.hobby,可以發(fā)現(xiàn)數(shù)據(jù)確實(shí)已經(jīng)改變,但是頁(yè)面是沒(méi)有相應(yīng)變化的,因?yàn)檫@樣通過(guò)數(shù)組下標(biāo)來(lái)改變數(shù)據(jù)的方式,vue監(jiān)測(cè)不到
正確寫法:this.student.hobby.splice(0,1,"學(xué)習(xí)");
總結(jié)一下
1.vue會(huì)監(jiān)視data中所有層次的數(shù)據(jù)
vue監(jiān)視的數(shù)據(jù)都是響應(yīng)式的
2.如何監(jiān)測(cè)對(duì)象中的數(shù)據(jù)
通過(guò)setter實(shí)現(xiàn)監(jiān)視,且要在new Vue時(shí)就傳入要監(jiān)測(cè)的數(shù)據(jù)
(1).對(duì)象中后追加的屬性,Vue默認(rèn)不做響應(yīng)式處理
(2).如需給后添加的屬性做響應(yīng)式處理
Vue.set(target, propertyName/index, value)
或
app.$set(target, propertyName/index, value)
3.如何監(jiān)測(cè)數(shù)組中的數(shù)據(jù)?
通過(guò)包裹數(shù)組更新元素的方法實(shí)現(xiàn),本質(zhì)上就是做了兩件事:
- 1.調(diào)用原生對(duì)應(yīng)的方法對(duì)數(shù)組進(jìn)行更新(push()、pop()、、、)
- 2.重新解析模版,進(jìn)而更新頁(yè)面
4.在Vue中修改數(shù)組中的某個(gè)元素一定要用如下方法:
- 1.使用這些API: push()、pop()、shift()、unshift()、splice()、sort()、reverse() 注意:以上為變更方法,會(huì)變更調(diào)用了這些方法的原始數(shù)組。也有非變更方法,例如filter()、concat()和slice(),它們不會(huì)變更原始數(shù)組,而總是返回一個(gè)新數(shù)組。當(dāng)使用非變更方法時(shí),可以用新數(shù)組直接替換舊數(shù)組
- 2.Vue.set()或app.$set()
特別注意:Vue.set()和app.$set()不能給app或者app的根數(shù)據(jù)對(duì)象(app._data)添加屬性
(target參數(shù)不可以是app或者app._data)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue.js中的計(jì)算屬性、監(jiān)視屬性與生命周期詳解
最近在學(xué)習(xí)vue,學(xué)習(xí)中遇到了一些感覺(jué)挺重要的知識(shí)點(diǎn),感覺(jué)有必要整理下來(lái),這篇文章主要給大家介紹了關(guān)于Vue.js中計(jì)算屬性、監(jiān)視屬性與生命周期的相關(guān)資料,需要的朋友可以參考下2021-06-06vue單頁(yè)面打包文件大?首次加載慢?nginx帶你飛,從7.5M到1.3M蛻變過(guò)程(推薦)
這篇文章主要介紹了vue單頁(yè)面打包文件大?首次加載慢?nginx帶你飛,從7.5M到1.3M蛻變過(guò)程,需要的朋友可以參考下2018-01-01vue3中使用props和emits并指定其類型與默認(rèn)值
props是Vue3中的一個(gè)重要概念,它允許我們將數(shù)據(jù)從父組件傳遞到子組件,下面這篇文章主要給大家介紹了關(guān)于vue3中使用props和emits并指定其類型與默認(rèn)值的相關(guān)資料,需要的朋友可以參考下2023-04-04vue自定義組件(通過(guò)Vue.use()來(lái)使用)即install的用法說(shuō)明
這篇文章主要介紹了vue自定義組件(通過(guò)Vue.use()來(lái)使用)即install的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08Vue Router根據(jù)后臺(tái)數(shù)據(jù)加載不同的組件實(shí)現(xiàn)
本文主要介紹了根據(jù)用戶所購(gòu)買服務(wù)的不同,有不同的頁(yè)面展現(xiàn)。文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08Vue使用Element-UI實(shí)現(xiàn)分頁(yè)效果全過(guò)程
element-ui官網(wǎng)上有分頁(yè)實(shí)現(xiàn)的功能,簡(jiǎn)單方便又好用,也有很多分頁(yè)的樣式,你可以根據(jù)需要去選擇自己想要的樣式,下面這篇文章主要給大家介紹了關(guān)于Vue使用Element-UI實(shí)現(xiàn)分頁(yè)效果的相關(guān)資料,需要的朋友可以參考下2023-04-04