详解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 相关文章推荐
网站被黑的假象--ARP欺骗之页面中加入一段js
May 16 Javascript
关于IE7 IE8弹出窗口顶上
Dec 22 Javascript
JS判断不能为空实例代码
Nov 26 Javascript
js获取checkbox复选框选中的选项实例
Aug 24 Javascript
javascript制作坦克大战全纪录(1)
Nov 27 Javascript
常用的Javascript设计模式小结
Dec 09 Javascript
jQuery抛物线运动实现方法(附完整demo源码下载)
Jan 08 Javascript
详解Jquery EasyUI tree 的异步加载(遍历指定文件夹,根据文件夹内的文件生成tree)
Feb 11 Javascript
vue-dialog的弹出层组件
May 25 Javascript
Cookies 和 Session的详解及区别
Apr 21 Javascript
浅谈JavaScript面向对象--继承
Mar 20 Javascript
vue-test-utils初使用详解
May 23 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中实现获取随机数组列表的自定义函数
2015/04/02 PHP
分享php分页的功能模块
2015/06/16 PHP
javascript 动态设置已知select的option的value值的代码
2009/12/16 Javascript
js实现的仿新浪微博完美的时间组件升级版
2011/12/20 Javascript
jquery的ajaxSubmit()异步上传图片并保存表单数据演示代码
2013/06/04 Javascript
js从10种颜色中随机取色实现每次取出不同的颜色
2013/10/23 Javascript
node.js中的fs.fstat方法使用说明
2014/12/15 Javascript
基于JavaScript实现快速转换文本语言(繁体中文和简体中文)
2016/03/07 Javascript
JS焦点图,JS 多个页面放多个焦点图的实例
2016/12/08 Javascript
jQuery实现使用sort方法对json数据排序的方法
2018/04/17 jQuery
详解React Native 屏幕适配(炒鸡简单的方法)
2018/06/11 Javascript
详解webpack打包第三方类库的正确姿势
2018/10/20 Javascript
vue-router启用history模式下的开发及非根目录部署方法
2018/12/23 Javascript
Vue框架TypeScript装饰器使用指南小结
2019/02/18 Javascript
jsonp跨域获取百度联想词的方法分析
2019/05/13 Javascript
ES6 Object方法扩展的应用实例分析
2019/06/25 Javascript
JavaScript 面向对象基础简单示例
2019/10/02 Javascript
解决vue admin element noCache设置无效的问题
2019/11/12 Javascript
nuxt 路由、过渡特效、中间件的实现代码
2020/11/06 Javascript
用python实现面向对像的ASP程序实例
2014/11/10 Python
python数据封装json格式数据
2018/03/04 Python
Pandas:Series和DataFrame删除指定轴上数据的方法
2018/11/10 Python
python matplotlib画图库学习绘制常用的图
2019/03/19 Python
Python Web版语音合成实例详解
2019/07/16 Python
Python字符串和正则表达式中的反斜杠('\')问题详解
2019/09/03 Python
python 实现弹球游戏的示例代码
2020/11/17 Python
CSS3 实现弹幕的示例代码
2017/08/07 HTML / CSS
html5跨域通讯之postMessage的用法总结
2013/11/07 HTML / CSS
MyHeritage美国:家族史研究和DNA测试的领先服务
2019/05/27 全球购物
节约用水演讲稿
2014/05/21 职场文书
县政府领导班子“四风”方面突出问题整改措施
2014/09/23 职场文书
2015年暑期社会实践方案
2015/07/14 职场文书
JavaScript严格模式不支持八进制的问题讲解
2021/11/07 Javascript
MySQL 服务和数据库管理
2021/11/11 MySQL
Python matplotlib绘制条形统计图 处理多个实验多组观测值
2022/04/21 Python
nginx rewrite功能使用场景分析
2022/05/30 Servers