详解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仿Excel表格编辑功能的实现代码
May 01 Javascript
原生Js实现元素渐隐/渐现(原理为修改元素的css透明度)
Jun 24 Javascript
jQuery获取选中内容及设置元素属性的方法
Jul 09 Javascript
jQuery选择器全集详解
Nov 24 Javascript
究竟什么是Node.js?Node.js有什么好处?
May 29 Javascript
js下将金额数字每三位一逗号分隔
Feb 19 Javascript
浅谈js中几种实用的跨域方法原理详解
Dec 02 Javascript
jquery 校验中国身份证号码实例详解
Apr 11 jQuery
使用express搭建一个简单的查询服务器的方法
Feb 09 Javascript
基于webpack4.X从零搭建React脚手架的方法步骤
Dec 23 Javascript
ES6知识点整理之模块化的应用详解
Apr 15 Javascript
Vue单文件组件开发实现过程详解
Jul 30 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 中文乱码解决办法总结分析
2009/07/30 PHP
phpMyAdmin链接MySql错误 个人解决方案
2009/12/28 PHP
php产生随机数的两种方法实例代码 输出随机IP
2011/04/08 PHP
用PHP实现的四则运算表达式计算实现代码
2011/08/02 PHP
利用curl抓取远程页面内容的示例代码
2013/07/23 PHP
实现PHP框架系列文章(6)mysql数据库方法
2016/03/04 PHP
浅谈php调用python文件
2019/03/29 PHP
php实现网页上一页下一页翻页过程详解
2019/06/28 PHP
使用prototype.js 的时候应该特别注意的几个问题.
2007/04/12 Javascript
疯掉了,尽然有js写的操作系统
2007/04/23 Javascript
地址栏上的一段语句,改变页面的风格。(教程)
2008/04/02 Javascript
JavaScript 加号(+)运算符号
2009/12/06 Javascript
Jquery判断IE6等浏览器的代码
2011/04/05 Javascript
读jQuery之四(优雅的迭代)
2011/06/20 Javascript
javascript中使用new与不使用实例化对象的区别
2015/06/22 Javascript
canvas实现图像布局填充功能
2017/02/06 Javascript
Bootstrap进度条实现代码解析
2017/03/07 Javascript
详解bootstrap-fileinput文件上传控件的亲身实践
2019/03/21 Javascript
小程序实现横向滑动日历效果
2019/10/21 Javascript
vue实现在线学生录入系统
2020/05/30 Javascript
vue 计算属性和侦听器的使用小结
2021/01/25 Vue.js
Python实现自动发送邮件功能
2021/03/02 Python
Python unittest模块用法实例分析
2018/05/25 Python
Sanic框架基于类的视图用法示例
2018/07/18 Python
Pycharm中切换pytorch的环境和配置的教程详解
2020/03/13 Python
CSS3中Animation属性的使用详解
2015/08/06 HTML / CSS
利用HTML5中的Canvas绘制一张笑脸的教程
2015/05/07 HTML / CSS
英国在线药房和在线医生:LloydsPharmacy
2019/10/21 全球购物
北承题目(C++)
2012/05/16 面试题
思想品德自我鉴定
2013/10/12 职场文书
环境科学专业个人求职信
2013/12/15 职场文书
撤诉书怎么写
2015/05/19 职场文书
基于Redis位图实现用户签到功能
2021/05/08 Redis
分享几个简单MySQL优化小妙招
2022/03/31 MySQL
Java虚拟机内存结构及编码实战分享
2022/04/07 Java/Android
Elasticsearch6.2服务器升配后的bug(避坑指南)
2022/09/23 Servers