vuex中遇到的坑,vuex資料改變,元件中頁面不渲染操作
vuex資料改變,元件中頁面不渲染
相信許多vuex新手都會遇到這樣的問題:
vuex資料更新後,外掛中使用資料的地方沒有更新
這樣的程式碼
data() { return { tableData: this.$store.state.AdminInfo }; }
然後在 template 中使用 tableData
<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 這樣就能隨時拿到最新的狀態值了
<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
將被定義或修改的屬性描述符
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上,
var vm = new Vue({ data:{ a:1 } }) // `vm.a` 是響應式的 vm.b = 2 // `vm.b` 是非響應式的
3.簡單介紹完了,我們來列舉幾個不重新整理的例項當然上述也是一種
第一種:修改物件的某一屬性
vue只會將已經在data中宣告的屬性變為響應,沒有宣告的是不響應的
<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'})
第二種:修改陣列物件的某一屬性
<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:'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。所以陣列中的也不例外,所以上述操作
改成:
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就是直接用原陣列接收改變的陣列,
<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'},methods: { click() { //改變陣列重新整理頁面 this.list.push({a:'css'}) },hadelClick(){ //重新賦值重新整理頁面 this.list = this.list.map(item=>{ item.a = 'css' return item }) } }) </script>
最後提供解決思路(以上都搞不定的話)
物件和陣列都是引用傳遞,要變成新陣列,來接受,就需要改變源,
第一種
let arr = []//新陣列 this.list.forEach(item=>{ //需要渲染的陣列 //執行你的操作,最後用放到arr中 arr.push(item) }) this.list = arr //相當於返回一個新陣列可以觸發渲染
第二種
//想要直接改變渲染陣列中的資料,但沒有渲染 //解決方法: let arr = this.list.slice(0);//深拷貝,(等價一個新的陣列) arr.forEach(item=>{ //執行你的操作 }) //賦值操作 this.list = arr
當然這裡只是簡單介紹了,有關深拷貝的詳細介紹,還請自行百度
上述如果都無法執行,但你的資料缺實修改了,可以使用this.$forceUpdate()方法 (強制重新整理)
//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'},methods: { click() { this.list[0] = {a:'css'} //頁面不渲染 console.log(this.list) //[{a:'css'},hadelClick(){ this.list[0] = {a:'css'} //頁面不渲染 console.log(this.list) //[{a:'css'},{a:'js'}] this.$forceUpdate();//強制重新整理 } } }) </script>
以上這篇vuex中遇到的坑,vuex資料改變,元件中頁面不渲染操作就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。