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