详解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 相关文章推荐
13 个JavaScript 性能提升技巧分享
Jul 26 Javascript
javascript自然分类法算法实现代码
Oct 11 Javascript
如何用JavaScript定义一个类
Sep 12 Javascript
js实现网页抽奖实例
Aug 05 Javascript
数组Array的一些方法(总结)
Feb 17 Javascript
xmlplus组件设计系列之树(Tree)(9)
May 02 Javascript
详解ES6之async+await 同步/异步方案
Sep 19 Javascript
微信小程序promsie.all和promise顺序执行
Oct 27 Javascript
Vue的路由动态重定向和导航守卫实例
Mar 17 Javascript
Vue前端开发规范整理(推荐)
Apr 23 Javascript
JavaScript实用代码小技巧
Aug 23 Javascript
推荐15个最好用的JavaScript代码压缩工具
Feb 13 Javascript
默认浏览器设置及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读取zip文件的方法示例
2016/11/17 PHP
JavaScript判断两种格式的输入日期的正确性的代码
2007/03/25 Javascript
多种方式实现JS调用后台方法进行数据交互
2013/08/20 Javascript
在父页面调用子页面的JS方法
2013/09/29 Javascript
jquery自定义滚动条插件示例分享
2014/02/21 Javascript
利用js制作html table分页示例(js实现分页)
2014/04/25 Javascript
深入分析原生JavaScript事件
2014/12/29 Javascript
JavaScript数组对象实现增加一个返回随机元素的方法
2015/07/27 Javascript
详解jQuery移动页面开发中的ui-grid网格布局使用
2015/12/03 Javascript
javascript获取select标签选中的值
2016/06/04 Javascript
jQuery版AJAX简易封装代码
2016/09/14 Javascript
jQuery的extend方法【三种】
2016/12/14 Javascript
css配合JavaScript实现tab标签切换效果
2018/10/11 Javascript
js实现倒计时器自定义时间和暂停
2019/02/25 Javascript
layui实现鼠标移动到单元格上显示数据的方法
2019/09/11 Javascript
[36:37]2014 DOTA2华西杯精英邀请赛5 24 VG VS iG
2014/05/25 DOTA
python list中append()与extend()用法分享
2013/03/24 Python
python使用webbrowser浏览指定url的方法
2015/04/04 Python
numpy中的delete删除数组整行和整列的实例
2018/05/09 Python
python爬取哈尔滨天气信息
2018/07/14 Python
Python使用正则表达式分割字符串的实现方法
2019/07/16 Python
python 模拟贷款卡号生成规则过程解析
2019/08/30 Python
python中web框架的自定义创建
2019/09/08 Python
基于TensorFlow的CNN实现Mnist手写数字识别
2020/06/17 Python
Python爬虫制作翻译程序的示例代码
2021/02/22 Python
Agoda西班牙:全球特价酒店预订
2017/06/03 全球购物
澳大利亚在线床零售商:Bedworks
2020/09/01 全球购物
村官学习十八大感想
2014/01/15 职场文书
党在我心中演讲稿
2014/09/02 职场文书
四风自我剖析材料
2014/09/30 职场文书
参观邀请函范文
2015/02/02 职场文书
农民工工资支付承诺书
2015/05/04 职场文书
2015年建筑工作总结报告
2015/05/04 职场文书
Jupyter notebook 更改文件打开的默认路径操作
2021/05/21 Python
JVM入门之类加载与字节码技术(类加载与类的加载器)
2021/06/15 Java/Android
javascript函数式编程基础
2021/09/15 Javascript