详解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 相关文章推荐
javascript椭圆旋转相册实现代码
Jan 16 Javascript
鼠标移动到图片名上,显示图片的简单实例
Jul 14 Javascript
CSS鼠标响应事件经过、移动、点击示例介绍
Sep 04 Javascript
javascript获取url上某个参数的方法
Nov 08 Javascript
js钢琴按钮波浪式图片排列效果代码分享
Aug 26 Javascript
Node.js 实现简单小说爬虫实例
Nov 18 Javascript
使用JS 插件qrcode.js生成二维码功能
Feb 20 Javascript
ionic App问题总结系列之ionic点击系统返回键退出App
Aug 19 Javascript
JS获取动态添加元素的方法详解
Jul 31 Javascript
vue 的 solt 子组件过滤过程解析
Sep 07 Javascript
layui form.render('select', 'test2') 更新渲染的方法
Sep 27 Javascript
vue项目中使用eslint+prettier规范与检查代码的方法
Jan 16 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获取用户IPv4或IPv6地址的代码
2012/11/15 PHP
php中$_POST与php://input的区别实例分析
2015/01/07 PHP
PHP中的流(streams)浅析
2015/07/02 PHP
Windows下PHP开发环境搭建教程(Apache+PHP+MySQL)
2016/06/13 PHP
Javascript学习笔记1 数据类型
2010/01/11 Javascript
js获取单元格自定义属性值的代码(IE/Firefox)
2010/04/05 Javascript
兼容IE、FireFox、Chrome等浏览器的xml处理函数js代码
2011/11/30 Javascript
js编码之encodeURIComponent使用介绍(asp,php)
2012/03/01 Javascript
jquery foreach使用示例
2013/09/12 Javascript
JSON 数字排序多字段排序介绍
2013/09/18 Javascript
详解JavaScript正则表达式中的global属性的使用
2015/06/16 Javascript
JavaScript使用RegExp进行正则匹配的方法
2015/07/11 Javascript
AngularJS解决ng界面长表达式(ui-set)的方法分析
2016/11/07 Javascript
webpack下实现动态引入文件方法
2018/02/22 Javascript
vue cli webpack中使用sass的方法
2018/02/24 Javascript
create-react-app安装出错问题解决方法
2018/09/04 Javascript
详解node.js创建一个web服务器(Server)的详细步骤
2021/01/15 Javascript
Python深入学习之内存管理
2014/08/31 Python
Python中MYSQLdb出现乱码的解决方法
2014/10/11 Python
Python中endswith()函数的基本使用
2015/04/07 Python
在Python中使用matplotlib模块绘制数据图的示例
2015/05/04 Python
django 通过ajax完成邮箱用户注册、激活账号的方法
2018/04/17 Python
python模块smtplib学习
2018/05/22 Python
python中int与str互转方法
2018/07/02 Python
python3 flask实现文件上传功能
2020/03/20 Python
python进行TCP端口扫描的实现
2018/12/21 Python
Python 音频生成器的实现示例
2019/12/24 Python
520使用Python实现“我爱你”表白
2020/05/20 Python
html svg生成环形进度条的实现方法
2019/09/23 HTML / CSS
美国在线鲜花速递:ProFlowers
2017/01/05 全球购物
Ralph Lauren意大利官方网站:时尚界最负盛名的品牌之一
2018/10/18 全球购物
RealTek面试题
2016/06/28 面试题
交通事故协议书范文
2014/04/16 职场文书
支行行长竞聘报告
2014/11/06 职场文书
详解redis在微服务领域的贡献
2021/10/16 Redis
Win11怎么启动任务管理器?Win11启动任务管理器的几种方法
2021/11/23 数码科技