Vue數(shù)據(jù)改變但頁(yè)面沒有變的幾種情況及解決方法
情況一:Vue無法檢測(cè)實(shí)例被創(chuàng)建時(shí)不存在于data中的變量
原因:由于 Vue 會(huì)在初始化實(shí)例時(shí)對(duì)data中的數(shù)據(jù)執(zhí)行g(shù)etter/setter轉(zhuǎn)化,所以變量必須在data對(duì)象上存在才能讓Vue將它轉(zhuǎn)化成響應(yīng)式的
new Vue({ data: {}, template: '<div>{{message}}</div>' }) this.message = 'Hello World' // 由于'message'不是響應(yīng)式的,頁(yè)面不會(huì)發(fā)生變化
解決方法:
new Vue({ data: { message: '' }, template: '<div>{{message}}</div>' }) this.message = 'Hello World'
情況二:Vue不能檢測(cè)到data中對(duì)象的動(dòng)態(tài)添加屬性和刪除屬性
動(dòng)態(tài)給對(duì)象新增屬性或刪除屬性是不會(huì)觸發(fā)視圖更新的,Vue識(shí)別不到
new Vue({ data: { obj:{ id: 1 } }, template: '<div>{{ obj.message }}</div>' }) this.obj.message = 'hello' // 不是響應(yīng)式的 delete this.obj.id //不是響應(yīng)式的
解決辦法:
// 動(dòng)態(tài)添加 - Vue.set Vue.set(this.obj, 'id', 001) // 動(dòng)態(tài)添加 - this.$set this.$set(this.obj, 'id', 002) // 動(dòng)態(tài)添加多個(gè) - Object.assign // 代替 Object.assign(this.obj, { a:1, b:2}) this.obj = Object.assign({}, this.obj, { a:1, b:2}) // 動(dòng)態(tài)移除 - Vue.delete Vue.delete(this.obj, 'name') // 動(dòng)態(tài)移除 - this.$delete this.$delete(this.obj, 'name')
情況三:變量為數(shù)組時(shí),不能通過索引值直接修改或者賦值,也不能修改數(shù)組的長(zhǎng)度
我們?cè)谛薷臄?shù)組數(shù)據(jù)的時(shí)候,應(yīng)該使用push()、pop()、shift()、unshift()、sort()、reverse()、splice()等原生的方法去操作數(shù)據(jù),因?yàn)閂ue可以直接檢測(cè)到這些方法所帶來的數(shù)組數(shù)據(jù)變化。
例如:
碼new Vue({ data: { items: ['a', 'b', 'c'] } }) this.items[1] = 'x' // 不是響應(yīng)式的 this.items[3] = 'd' // 不是響應(yīng)式的 this.items.length = 2 // 不是響應(yīng)式的
解決方法:
// Vue.set Vue.set(this.items, 4, 'd') // this.$set this.$set(this.items, 4, 'd') // Array.prototype.splice // 修改操作: splice(你要修改的元素索引位置, 1, 修改后的值) // 添加操作: splice(你要添加到那個(gè)元素的后面就寫到那個(gè)元素的索引+1, 0, 要添加的值) // 刪除操作: splice(你要?jiǎng)h除的元素的索引, 1) this.items.splice(indexOfItem, 4, 'd') // 修改長(zhǎng)度 this.items.splice(3)
情況四: 異步獲取接口數(shù)據(jù),DOM數(shù)據(jù)不發(fā)生變化
原因:Vue在更新 DOM 時(shí)是異步執(zhí)行的。當(dāng)數(shù)據(jù)變化時(shí),Vue不會(huì)立即更新DOM,而是等到下一次事件循環(huán)再執(zhí)行更新。如果需要立即更新視圖,可以使用Vue.nextTick(callback)方法
例如1:修改完數(shù)據(jù)之后想立刻操作 DOM 元素,就需要使用nextTick
<div id='example'>{{message}}</div> var vm = new Vue({ el: '#example', data: { message: '123' } }) vm.message = 'new message' // 更改數(shù)據(jù) vm.$el.textContent === 'new message' // false vm.$el.style.color = 'red' // 頁(yè)面沒有變化
解決辦法:
<div id='example'>{{message}}</div> var vm = new Vue({ el: '#example', data: { message: '123' } }) vm.message = 'new message' // 更改數(shù)據(jù) // 使用 Vue.nextTick(callback) callback將在 DOM 更新完成后被調(diào)用 Vue.nextTick(function() { vm.$el.textContent === 'new message' // true vm.$el.style.color = 'red' // 文字顏色變成紅色 })
例如2: 如果想要在created()中操作DOM,也需要使用nextTick,因?yàn)樵诖穗A段,DOM還未渲染
created(){ this.$nextTick(() => { // 不使用this.$nextTick()會(huì)報(bào)錯(cuò) that.$refs.btn.innerHTML = 'created中更改了按鈕內(nèi)容' }) }
情況五: 循環(huán)嵌套層級(jí)太深,視圖不更新
當(dāng)嵌套太深時(shí),頁(yè)面也可能不更新,此時(shí)可以讓頁(yè)面強(qiáng)制刷新
因?yàn)閂ue修改數(shù)據(jù)是異步執(zhí)行的,所以是不不會(huì)立即更新,會(huì)等到下一次DOM更新循環(huán)結(jié)束后,統(tǒng)一更新發(fā)生在這一次循環(huán)中修改的數(shù)據(jù),然后同步視圖更新,所以我們可以修改后自己手動(dòng)強(qiáng)制更新視圖。
this.$forceUpdate()
迫使Vue實(shí)例重新(render)渲染虛擬DOM,注意并不是重新加載組件。
結(jié)合 Vue 的生命周期,調(diào)用$forceUpdate后只會(huì)觸發(fā)beforeUpdate和 updated 兩個(gè)鉤子函數(shù),不會(huì)觸發(fā)其他的鉤子函數(shù)。
它僅僅影響實(shí)例本身和插入插槽內(nèi)容的子組件,而不是所有子組件。
js 代碼解讀復(fù)制代碼// 官方說如果你現(xiàn)在的場(chǎng)景需要用forceUpdate方法,那么99%是你的操作有問題
this.$forceUpdate()
情況六: 路由參數(shù)變化時(shí),頁(yè)面不更新(數(shù)據(jù)不更新)
例如:
<div id='app'> <ul> <li><router-link to='/home/foo'>To Foo</router-link></li> <li><router-link to='/home/baz'>To Baz</router-link></li> <li><router-link to='/home/bar'>To Bar</router-link></li> </ul> <router-view></router-view> </div> const Home = { template: `<div>{{message}}</div>`, data() { return { message: this.$route.params.name } } } const router = new VueRouter({ mode: 'history', routes: [ {path: '/home', component: Home}, {path: '/home/:name, component: Home} ] }) new Vue({ el: '#app', router })
上段代碼中,我們?cè)诼酚蓸?gòu)建選項(xiàng)routes中配置了一個(gè)動(dòng)態(tài)路由’home/:name’,他們共用了一個(gè)路由組件Home,這代表他們復(fù)用 RouterView
當(dāng)進(jìn)行路由切換時(shí),頁(yè)面只會(huì)渲染第一次路由匹配到的參數(shù),之后再進(jìn)行路由切換時(shí),message是沒有變化的。
解決方法:
通過watch 監(jiān)聽 $route的變化
const Home = { template: `<div>{{message}}</div>`, data() { return { message: this.$route.params.name } }, watch: { '$route': function(){ this.message = this.$route.params.name } } }, const router = new VueRouter({ mode: 'history', routes: [ {path: '/home', component: Home}, {path: '/home/:name, component: Home} ] }) new Vue({ el: '#app', router })
給綁定key屬性,這樣Vue就會(huì)認(rèn)為這是不同的
弊端:如果從 /home 跳轉(zhuǎn)到 /user 等其他路由下,我們是不用擔(dān)心組件更新問題的,所以這個(gè)時(shí)候key屬性是多余的。
<div id='app'> ... <router-view :key='key'></router-view> </div>
情況七:變量通過賦值來定義的
在 Vue 中有兩種類型的變量:響應(yīng)式變量和非響應(yīng)式變量。
在后端獲取的變量通常是響應(yīng)式變量,也就是說它們會(huì)被 Vue 檢測(cè)到變化并同步到頁(yè)面上,如果你修改了這些響應(yīng)式變量,頁(yè)面會(huì)隨之改變。
而通過賦值來定義的變量,通常是非響應(yīng)式變量,如果你修改了這些非響應(yīng)式變量,Vue并不會(huì)監(jiān)測(cè)到他們的變化,所以頁(yè)面不會(huì)改變。
如果你需要是一個(gè)非響應(yīng)式變量變成響應(yīng)式變量,可以使用Vue.set方法或者數(shù)組的變異方法(例如push、splice等)
例1:Vue.set(對(duì)象,添加的key, 屬性值)
Vue.set // 這個(gè)是直接用在Vue身上的。例如:Vue.set(對(duì)象, 添加的key, 屬性值) // 常見于 xx.js文件中 // 注意: js文件中,需要引入vue,比如 import Vue from vue
例2:this.$set(對(duì)象,添加的key, 屬性值)
this.$set // 這個(gè)是用在vm或vc實(shí)例上的,比如vue文件中, // this.$set(要添加屬性的對(duì)象,要添加屬性的名稱, 要設(shè)置的新屬性值) // 常見于 xx.vue文件中
this.$set 是 Vue.js 中的一個(gè)方法,用于解決Vue不能檢測(cè)到對(duì)象屬性的添加或刪除的問題。當(dāng)需要?jiǎng)討B(tài)地向響應(yīng)式對(duì)象添加一個(gè)屬性,并確保這個(gè)新屬性同樣是響應(yīng)式的(即當(dāng)期值改變時(shí),視圖也會(huì)更新),可以使用this.$set
在Vue3中,this.$set已被移除,因?yàn)閂ue3使用了proxy來實(shí)現(xiàn)響應(yīng)式,這樣在數(shù)據(jù)變化后能夠更精確的檢測(cè)到屬性的添加和刪除。但你也可以使用set()方法去代替Vue2的this.$set。
情況八:使用插槽 對(duì)父組件進(jìn)行傳參渲染
頁(yè)面組件初始化渲染的時(shí)候,是用參數(shù)傳進(jìn)父組件,父組件又包含的模板插槽,初次渲染后,對(duì)組件內(nèi)數(shù)據(jù)進(jìn)行修改,此時(shí)你會(huì)發(fā)現(xiàn)怎么修改都無效,無論你的數(shù)據(jù)是否響應(yīng)式綁定!因?yàn)榇藭r(shí)插槽模板已經(jīng)渲染完,不會(huì)再進(jìn)行二次渲染,你要做的就是使它重新渲染
可以使用v-if或者v-for去遍歷你的插槽,使它重新渲染
<template v-for="item in arr" :key="item.id" #[`${item.label}-header`] > <xxx /> </template>
以上就是Vue數(shù)據(jù)改變但頁(yè)面沒有變的幾種情況及解決方法的詳細(xì)內(nèi)容,更多關(guān)于Vue數(shù)據(jù)改變但頁(yè)面沒有變的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue集成openlayers加載geojson并實(shí)現(xiàn)點(diǎn)擊彈窗教程
這篇文章主要為大家詳細(xì)介紹了vue集成openlayers加載geojson并實(shí)現(xiàn)點(diǎn)擊彈窗教程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09Vue+Three加載glb文件報(bào)錯(cuò)問題及解決
當(dāng)使用Three.js加載GLB模型時(shí),遇到加載錯(cuò)誤常常是路徑問題,解決方案:1. 將GLB模型文件置于public目錄,避免打包時(shí)路徑編碼變化;2. 從node_modules的three庫(kù)中復(fù)制draco解碼器至public目錄;3. 確認(rèn)場(chǎng)景、攝像機(jī)和光源設(shè)置正確2024-10-10vue項(xiàng)目刷新當(dāng)前頁(yè)面的三種方法
這篇文章主要介紹了vue項(xiàng)目刷新當(dāng)前頁(yè)面的三種方法,本文圖文并茂給大家介紹的非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-12-12python虛擬環(huán)境 virtualenv的簡(jiǎn)單使用
virtualenv是一個(gè)創(chuàng)建隔絕的Python環(huán)境的工具。這篇文章主要介紹了python虛擬環(huán)境 virtualenv的簡(jiǎn)單使用,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-01-01總結(jié)4個(gè)方面優(yōu)化Vue項(xiàng)目
在本篇文章里我們給大家整理了一篇關(guān)于優(yōu)化VUE項(xiàng)目的四個(gè)總要點(diǎn),對(duì)此有需要的朋友們學(xué)習(xí)下天。2019-02-02vue3+vite2中使用svg的方法詳解(親測(cè)可用)
vue2的時(shí)候使用的是字體圖標(biāo),缺點(diǎn)就是比較單一,到了vue3,相信瀏覽器的性能起來,所以這里記錄一下,下面這篇文章主要給大家介紹了關(guān)于vue3+vite2中使用svg的相關(guān)資料,需要的朋友可以參考下2022-08-08vue2.0中自適應(yīng)echarts圖表、全屏插件screenfull的使用
這篇文章主要介紹了vue2.0中自適應(yīng)echarts圖表、全屏插件screenfull的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08Vue瀏覽器鏈接與接口參數(shù)實(shí)現(xiàn)加密過程詳解
這篇文章主要介紹了Vue瀏覽器鏈接與接口參數(shù)實(shí)現(xiàn)加密過程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-12-12