详解Vue改变数组中对象的属性不重新渲染View的解决方案


Posted in Javascript onSeptember 21, 2018

在解决问题之前,我们先来了解下 vue响应性原理: Vue最显著的一个功能是响应系统-- 模型只是一个普通对象,修改对象则会更新视图。

受到javascript的限制,Vue不能检测到对象属性的添加或删除,因为vue在初始化实列时将属性转为getter/setter,所以属性必须在data对象上才能让vue转换它。

但是vue可以使用 Vue.set(object, key, value)方法将响应属性添加到嵌套的对象上:如下代码:

Vue.set(obj, '_isHover', true);

或者可以使用vm.$set的实列方法,也是Vue.set方法的别名:

this.$set(obj, '_isHover', false);

问题: 页面上多个item项, 当我鼠标移动上去的时候,我想在该数组中的对象添加一个属性 isHover=true, 当鼠标移出的时候,我想让该属性变为 isHover=false,然后希望改变对象的属性的时候让其重新渲染view层,重新执行rowClasses方法,然后该方法会判断 isHover是否等于true,如果为true的话,让其增加一个类名。

代码如下:

<!DOCTYPE html>
<html>
 <head>
  <title>演示Vue</title>
  <style>
   * {margin: 0; padding: 0;}
   ul, li {list-style: none;}
   #app {width: 800px; margin: 20px auto; border:1px solid #ccc; border-bottom: none;}
   #app li {height: 32px; line-height: 32px; border-bottom: 1px solid #ccc;}
   #app li.bgColor {background-color: red;}
  </style>
 </head>
 <body>
  <div id='app'>
   <ul>
    <li 
     v-for="(item, index) in items" 
     @mouseenter.stop="handleMouseIn(index)"
     @mouseleave.stop="handleMouseOut(index)"
     :class="rowClasses(index)"
    >
     <span>{{item.name}}</span>
    </li>
   </ul>
  </div>
 </body>
 <script src="https://tugenhua0707.github.io/vue/vue1/vue.js"></script>
 <script type="text/javascript">
  new Vue({
   el: '#app',
   data: {
    items: [
     {name: 'kongzhi'},
     {name: 'longen'},
     {name: 'tugenhua'}
    ]
   },
   computed: {
    
   },
   methods: {
    rowClasses (index) {
     return [
      {
       [`bgColor`]: this.$data.items[index] && this.$data.items[index]._isHover
      }
     ]
    },
    handleMouseIn(index) {
     if (this.$data.items[index]._isHover) {
      return;
     }
     console.log(111); // 可以执行到
     this.$data.items[index]._isHover = true;
    },
    handleMouseOut(index) {
     this.$data.items[index]._isHover = false;
    }
   }
  });
 </script>
</html>

查看效果

可以看到鼠标移动上去的时候 没有效果。

解决的方案如下:

1. 使用 Object.assign

鼠标移动上去的时候 代码可以改成如下:

this.$data.items[index]._isHover = true;
this.$data.items = Object.assign({}, this.$data.items);

鼠标移出的时候,代码改成如下:

this.$data.items[index]._isHover = false;
this.$data.items = Object.assign({}, this.$data.items);

代码如下:

<!DOCTYPE html>
<html>
 <head>
  <title>演示Vue</title>
  <style>
   * {margin: 0; padding: 0;}
   ul, li {list-style: none;}
   #app {width: 800px; margin: 20px auto; border:1px solid #ccc; border-bottom: none;}
   #app li {height: 32px; line-height: 32px; border-bottom: 1px solid #ccc;}
   #app li.bgColor {background-color: red;}
  </style>
 </head>
 <body>
  <div id='app'>
   <ul>
    <li 
     v-for="(item, index) in items" 
     @mouseenter.stop="handleMouseIn(index)"
     @mouseleave.stop="handleMouseOut(index)"
     :class="rowClasses(index)"
    >
     <span>{{item.name}}</span>
    </li>
   </ul>
  </div>
 </body>
 <script src="https://tugenhua0707.github.io/vue/vue1/vue.js"></script>
 <script type="text/javascript">
  new Vue({
   el: '#app',
   data: {
    items: [
     {name: 'kongzhi'},
     {name: 'longen'},
     {name: 'tugenhua'}
    ]
   },
   computed: {
    
   },
   methods: {
    rowClasses (index) {
     return [
      {
       [`bgColor`]: this.$data.items[index] && this.$data.items[index]._isHover
      }
     ]
    },
    handleMouseIn(index) {
     if (this.$data.items[index]._isHover) {
      return;
     }
     console.log(111); // 可以执行到
     this.$data.items[index]._isHover = true;
     this.$data.items = Object.assign({}, this.$data.items);
    },
    handleMouseOut(index) {
     this.$data.items[index]._isHover = false;
     this.$data.items = Object.assign({}, this.$data.items);
    }
   }
  });
 </script>
</html>

查看效果

2. 使用Vue.set(object, key, value)方法将响应属性添加到嵌套的对象上。

鼠标移动上去的时候 代码可以改成如下:

this.$set(this.$data.items[index], '_isHover', true);

鼠标移出的时候,代码改成如下:

this.$set(this.$data.items[index], '_isHover', false);

所有的代码如下:

<!DOCTYPE html>
<html>
 <head>
  <title>演示Vue</title>
  <style>
   * {margin: 0; padding: 0;}
   ul, li {list-style: none;}
   #app {width: 800px; margin: 20px auto; border:1px solid #ccc; border-bottom: none;}
   #app li {height: 32px; line-height: 32px; border-bottom: 1px solid #ccc;}
   #app li.bgColor {background-color: red;}
  </style>
 </head>
 <body>
  <div id='app'>
   <ul>
    <li 
     v-for="(item, index) in items" 
     @mouseenter.stop="handleMouseIn(index)"
     @mouseleave.stop="handleMouseOut(index)"
     :class="rowClasses(index)"
    >
     <span>{{item.name}}</span>
    </li>
   </ul>
  </div>
 </body>
 <script src="https://tugenhua0707.github.io/vue/vue1/vue.js"></script>
 <script type="text/javascript">
  new Vue({
   el: '#app',
   data: {
    items: [
     {name: 'kongzhi'},
     {name: 'longen'},
     {name: 'tugenhua'}
    ]
   },
   computed: {
    
   },
   methods: {
    rowClasses (index) {
     return [
      {
       [`bgColor`]: this.$data.items[index] && this.$data.items[index]._isHover
      }
     ]
    },
    handleMouseIn(index) {
     if (this.$data.items[index]._isHover) {
      return;
     }
     console.log(111); // 可以执行到
     this.$set(this.$data.items[index], '_isHover', true);
    },
    handleMouseOut(index) {
     this.$set(this.$data.items[index], '_isHover', false);
    }
   }
  });
 </script>
</html>

查看效果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery Ajax 全解析
Feb 08 Javascript
js 数值项目的格式化函数代码
May 14 Javascript
javascript实现信息的显示和隐藏如注册页面
Dec 03 Javascript
js 弹出新页面避免被浏览器、ad拦截的一种新方法
Apr 30 Javascript
JS实现点击文字对应DIV层不停闪动效果的方法
Mar 02 Javascript
jQuery选择器之基本选择器与层次选择器
Mar 03 Javascript
input获取焦点时底部菜单被顶上来问题的解决办法
Jan 24 Javascript
node koa2实现上传图片并且同步上传到七牛云存储
Jul 31 Javascript
详解用Node.js实现Restful风格webservice
Sep 29 Javascript
vue2使用keep-alive缓存多层列表页的方法
Sep 21 Javascript
vue router 通过路由来实现切换头部标题功能
Apr 24 Javascript
vue使用lodop打印控件实现浏览器兼容打印的方法
Feb 07 Vue.js
默认浏览器设置及vue自动打开页面的方法
Sep 21 #Javascript
详解Vue中数组和对象更改后视图不刷新的问题
Sep 21 #Javascript
详解vue 数组和对象渲染问题
Sep 21 #Javascript
vue 2.8.2版本配置刚进入时候的默认页面方法
Sep 21 #Javascript
Puppeteer环境搭建的详细步骤
Sep 21 #Javascript
jQuery序列化form表单数据为JSON对象的实现方法
Sep 20 #jQuery
JavaScript 高性能数组去重的方法
Sep 20 #Javascript
You might like
php 高效率写法 推荐
2010/02/21 PHP
php join函数应用
2011/05/04 PHP
win7 64位系统 配置php最新版开发环境(php+Apache+mysql)
2014/08/15 PHP
深入理解PHP之源码目录结构与功能说明
2016/06/01 PHP
NiftyCube——轻松实现圆角边框
2007/02/20 Javascript
Javascript实现返回上一页面并刷新的小例子
2013/12/11 Javascript
iframe里面的元素触发父窗口元素事件的jquery代码
2014/10/19 Javascript
jquery实现的省市区三级联动
2015/04/02 Javascript
jquery插件EasyUI中form表单提交实例分享
2016/01/11 Javascript
JS锚点的设置与使用方法
2016/09/05 Javascript
微信小程序 五星评分的实现实例
2017/08/04 Javascript
Bootstrap 模态框(Modal)带参数传值实例
2017/08/20 Javascript
js jquery 获取某一元素到浏览器顶端的距离实现方法
2018/09/05 jQuery
Vue文件配置全局变量的实例
2018/09/06 Javascript
Vue实现Layui的集成方法步骤
2020/04/10 Javascript
python生成器的使用方法
2013/11/21 Python
浅谈Python的Django框架中的缓存控制
2015/07/24 Python
读取本地json文件,解析json(实例讲解)
2017/12/06 Python
使用Python获取网段IP个数以及地址清单的方法
2018/11/01 Python
浅谈Python采集网页时正则表达式匹配换行符的问题
2018/12/20 Python
基于多进程中APScheduler重复运行的解决方法
2019/07/22 Python
Python 时间戳之获取整点凌晨时间戳的操作方法
2020/01/28 Python
python,Java,JavaScript实现indexOf
2020/09/09 Python
15个Pythonic的代码示例(值得收藏)
2020/10/29 Python
canvas线条的属性详解
2018/03/27 HTML / CSS
国际贸易个人求职信范文
2014/01/04 职场文书
产品发布会策划方案
2014/05/12 职场文书
公司门卫岗位职责范本
2014/07/08 职场文书
质量主管工作职责
2014/09/26 职场文书
初中差生评语
2014/12/29 职场文书
公司慰问信范文
2015/03/23 职场文书
行政前台岗位职责
2015/04/16 职场文书
2015年科研工作总结范文
2015/05/13 职场文书
三好学生主要事迹材料
2015/11/03 职场文书
PHP使用非对称加密算法RSA
2021/04/21 PHP
MongoDB日志切割的三种方式总结
2021/09/15 MongoDB