vuex數據改變,組件中頁面不渲染
相信許多vuex新手都會遇到這樣的問題:
vuex數據更新后,插件中使用數據的地方沒有更新
這樣的代碼
1
2
3
4
5
|
data() { return { tableData: this .$store.state.AdminInfo }; } |
然后在 template 中使用 tableData
1
2
3
4
|
< el-table :data = "tableData" class = "tablePst" > < el-table-column label = "登錄名" prop = "loginname" ></ el-table-column > < el-table-column label = "真實姓名" prop = "realname" ></ el-table-column > </ el-table > |
這樣的話,就會出現數據改變不渲染的問題
問題
要解決問題,就得理解vue生命周期,頁面加載前 tableData 獲取 store 里的值賦給自己,這樣 tableData 只有一初始值,后續vuex中狀態發生改變,并不會再次賦值給 tableData ,除非頁面刷新重新加載,組件生命周期重新開始,才能拿到最新的值
解決
1.去掉組件中 tableData 的狀態,在模板中直接使用 $store.state.AdminInfo 這樣就能隨時拿到最新的狀態值了
1
2
3
4
|
< el-table :data = "$store.state.AdminInfo" class = "tablePst" > < el-table-column label = "登錄名" prop = "loginname" ></ el-table-column > < el-table-column label = "真實姓名" prop = "realname" ></ el-table-column > </ el-table > |
2.使用mapState,把vuex中的狀態暴露給組件,再使用,具體見文檔 vuex mapState官方文檔.
補充知識:解決vue修改數據頁面不重新渲染問題(Vue中數組和對象更改后視圖不刷新)
vue渲染機制和如何解決數據修改頁面不刷新問題的多種方法
本文不講原理,只講干貨易懂易學,(感覺能學到知識,麻煩給小編來個贊!)
首先 第一點,vue底層是 將data對象傳人,使用Object.definePropety,轉換為getter和setter,所以,vue不支持IE8.
1.簡單介紹一下Object.definePropety,
Object.defineProperty(obj, prop, descriptor)
//參數
obj
要在其上定義屬性的對象。
prop
要定義或修改的屬性的名稱。
descriptor
將被定義或修改的屬性描述符
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var obj = {} Object.defineProperty(obj, 'name' , { get: function () { console.log( '我的名字叫' +name); return name; }, set: function (value) { console.log( '你叫' +value) name = value; } }); obj.name = '張三' ; //你叫張三 obj.name //我的名字叫張三 |
從上述我們可以簡單發現。當我們對這個對象的name屬性賦值的時候,就會觸發set方法,獲取name屬性的時候就會觸發get方法;
2.因此在vue中寫在data中的屬性是是可以轉換成getter和setter,換一句話就是響應式的,其他定義在data之外的數據,是無法響應的渲染,意思就是改變數據頁面也不會刷新,所以一切要渲染到頁面上的數據,必須寫在data中,
不需要的,可以定義在this上,
1
2
3
4
5
6
7
8
9
10
|
var vm = new Vue({ data:{ a:1 } }) // `vm.a` 是響應式的 vm.b = 2 // `vm.b` 是非響應式的 |
3.簡單介紹完了,我們來列舉幾個不刷新的實例當然上述也是一種
第一種:修改對象的某一屬性
vue只會將已經在data中聲明的屬性變為響應,沒有聲明的是不響應的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<template> <div> <div v- for = 'item in list' >{{item}}</div> <button @click= 'click' >改變</button> <button @click= 'hadelClick' >解決方法</button> </div> </template> <script> export default ({ data(){ return { list:{a: 'a' ,b: 'b' }, } }, methods: { click() { // 未聲明不觸發渲染 this .list.c= 'c' }, hadelClick(){ // 解決方法,使用vue提供的$set方法來觸發渲染 this .$set( this .list, 'd' , 'd' ) } } }) </script> |
當然如果我們要添加多個屬性,可以使用 Object.assign() 用于將所有可枚舉屬性的值從一個或多個源對象復制到目標對象,并返回目標對象。(簡單說就是合并到第一個參數中)
this.list = Object.assign({},this.list,{c:'c',d:'d'})
第二種:修改數組對象的某一屬性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<template> <div> <div v- for = 'item in list' >{{item.a}}</div> <button @click= 'click' >改變</button> <button @click= 'hadelClick' >解決方法</button> </div> </template> <script> export default ({ data(){ return { list:[{a: 'vue' },{a: 'react' },{a: 'js' }], } }, methods: { click() { //想這樣直接給數組中的某一個對象直接賦值,是無法動態渲染的(即改變了數據,頁面不渲染) this .list[0] = {a: 'css' } //頁面不渲染 console.log( this .list) //[{a:'css'},{a:'react'},{a:'js'}] }, hadelClick(){ // 解決方法,使用vue提供的$set方法來觸發渲染 this .$set( this .list[1], 'a' , 'css' ) console.log( this .list) //[{a:'css'},{a:'css'},{a:'js'}] } } }) </script> |
當然前文講過,vue會遍歷data中的數據,將對象轉換成setter和getter。所以數組中的也不例外,所以上述操作
改成:
1
2
3
4
|
click(){ this .list[0].a = css //依舊能夠觸發setter。實現數據重新渲染 } } |
在vue中更多的是數組的操作不刷新,一種是通過索引賦值,一種是修改數組長度,如何解決呢?
vue官方也給了方法
數組的API,中能夠改變原始數組的都能觸發更新;
1、push()
2、pop()
3、shift()
4、unshift()
5、splice()
6、sort()
7、reverse()
第二種是返回一個新數組的,這種數組在引用地址上已經發生根本改變,這樣的賦值操作是能觸發更新的(這是處理不刷新的思路,就是改變引用地址,重新賦值觸發更新)
簡單說,用數組的API就是直接用原數組接收改變的數組,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<template> <div> <div v- for = 'item in list' >{{item.a}}</div> <button @click= 'click' >改變原數組</button> <button @click= 'hadelClick' >不改變原數組</button> </div> </template> <script> export default ({ data(){ return { list:[{a: 'vue' },{a: 'react' },{a: 'js' }], } }, methods: { click() { //改變數組刷新頁面 this .list.push({a: 'css' }) }, hadelClick(){ //重新賦值刷新頁面 this .list = this .list.map(item=>{ item.a = 'css' return item }) } }) </script> |
最后提供解決思路(以上都搞不定的話)
對象和數組都是引用傳遞,要變成新數組,來接受,就需要改變源,
第一種
1
2
3
4
5
6
|
let arr = [] //新數組 this .list.forEach(item=>{ //需要渲染的數組 //執行你的操作,最后用放到arr中 arr.push(item) }) this .list = arr //相當于返回一個新數組可以觸發渲染 |
第二種
1
2
3
4
5
6
7
8
|
//想要直接改變渲染數組中的數據,但沒有渲染 //解決方法: let arr = this .list.slice(0); //深拷貝,(等價一個新的數組) arr.forEach(item=>{ //執行你的操作 }) //賦值操作 this .list = arr |
當然這里只是簡單介紹了,有關深拷貝的詳細介紹,還請自行百度
上述如果都無法執行,但你的數據缺實修改了,可以使用this.$forceUpdate()方法 (強制刷新)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
//this.$forceUpdate();//強制刷新 <template> <div> <div v- for = 'item in list' >{{item.a}}</div> <button @click= 'click' >改變</button> <button @click= 'hadelClick' >解決方法</button> </div> </template> <script> export default ({ data(){ return { list:[{a: 'vue' },{a: 'react' },{a: 'js' }], } }, methods: { click() { this .list[0] = {a: 'css' } //頁面不渲染 console.log( this .list) //[{a:'css'},{a:'react'},{a:'js'}] }, hadelClick(){ this .list[0] = {a: 'css' } //頁面不渲染 console.log( this .list) //[{a:'css'},{a:'react'},{a:'js'}] this .$forceUpdate(); //強制刷新 } } }) </script> |
以上這篇vuex中遇到的坑,vuex數據改變,組件中頁面不渲染操作就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/weixin_42204698/article/details/89888635