vuex中遇到的坑,vuex数据改变,组件中页面不渲染操作


Posted in Javascript onNovember 16, 2020

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:'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。所以数组中的也不例外,所以上述操作

改成:

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'},{a:'react'},{a:'js'}],
   }
  },
  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'},{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数据改变,组件中页面不渲染操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
用js实现的检测浏览器和系统的函数
Apr 09 Javascript
createElement与createDocumentFragment的点点区别小结
Dec 19 Javascript
删除select中所有option选项jquery代码
Aug 12 Javascript
使用CSS3的scale实现网页整体缩放
Mar 18 Javascript
容易造成JavaScript内存泄露几个方面
Sep 04 Javascript
原生JS和JQuery动态添加、删除表格行的方法
May 28 Javascript
JS实现图片的不间断连续滚动的简单实例
Jun 03 Javascript
js定义类的几种方法(推荐)
Jun 08 Javascript
详解springmvc 接收json对象的两种方式
Dec 06 Javascript
jQuery实现遮罩层登录对话框
Dec 29 Javascript
JavaScript 数组去重并统计重复元素出现的次数实例
Dec 14 Javascript
js实现自动锁屏功能
Jun 02 Javascript
基于Vue+Webpack拆分路由文件实现管理
Nov 16 #Javascript
小程序实现上下切换位置
Nov 16 #Javascript
小程序实现点击tab切换左右滑动
Nov 16 #Javascript
微信小程序实现滚动Tab选项卡
Nov 16 #Javascript
小程序实现tab标签页
Nov 16 #Javascript
vue+Element-ui实现登录注册表单
Nov 17 #Javascript
Vue+Element-U实现分页显示效果
Nov 15 #Javascript
You might like
php开发工具之vs2005图解
2008/01/12 PHP
ie6 动态缩略图不显示的原因
2009/06/21 PHP
php下mysql数据库操作类(改自discuz)
2010/07/03 PHP
PHP中怎样保持SESSION不过期 原理及方案介绍
2013/08/08 PHP
php使用array_rand()函数从数组中随机选择一个或多个元素
2014/04/28 PHP
浅谈Coreseek、Sphinx-for-chinaese、Sphinx+Scws的区别
2016/12/15 PHP
php实现基于pdo的事务处理方法示例
2017/07/21 PHP
one.php 多项目、函数库、类库 统一为一个版本的方法
2020/08/24 PHP
javascript concat数组累加 示例
2009/09/03 Javascript
js弹窗代码 可以指定弹出间隔
2010/07/03 Javascript
获取客户端电脑日期时间js代码(jquery)
2012/09/12 Javascript
js实现点小图看大图效果的思路及示例代码
2013/10/28 Javascript
JS Replace 全部替换字符的用法小结
2013/12/24 Javascript
jqGrid读取选择的多行的某个属性代码
2014/05/18 Javascript
javascript删除一个html元素节点的方法
2014/12/20 Javascript
javascript实现禁止右键和F12查看源代码
2014/12/26 Javascript
javascript实现俄罗斯方块游戏的思路和方法
2015/04/27 Javascript
jQuery实现二级下拉菜单效果
2016/01/05 Javascript
AngularJS出现$http异步后台无法获取请求参数问题的解决方法
2016/11/03 Javascript
js实现图片实时时钟
2020/01/15 Javascript
python备份文件以及mysql数据库的脚本代码
2013/06/10 Python
python对象及面向对象技术详解
2016/07/19 Python
基于Python中numpy数组的合并实例讲解
2018/04/04 Python
通过pycharm使用git的步骤(图文详解)
2019/06/13 Python
使用OpenCV实现仿射变换—平移功能
2019/08/29 Python
django 实现后台从富文本提取纯文本
2020/07/02 Python
Opencv python 图片生成视频的方法示例
2020/11/18 Python
英国巧克力贸易公司:Chocolate Trading Company
2017/03/21 全球购物
理肤泉俄罗斯官网:La Roche-Posay俄罗斯
2018/07/24 全球购物
澳大利亚购买最佳炊具品牌网站:Cookware Brands
2019/02/16 全球购物
什么是用户模式(User Mode)与内核模式(Kernel Mode) ?
2015/09/07 面试题
花店创业计划书范文
2014/02/07 职场文书
写给老师的感谢信
2015/01/20 职场文书
最美乡村教师观后感
2015/06/11 职场文书
实验室安全管理制度
2015/08/05 职场文书
Go timer如何调度
2021/06/09 Golang