详解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 获取json数据实现代码
Apr 27 Javascript
jquery鼠标滑过提示title具体实现代码
Aug 06 Javascript
JavaScript获取图片的原始尺寸以宽度为例
May 04 Javascript
Javascript控制input输入时间格式的方法
Jan 28 Javascript
原生JS实现拖拽图片效果
Aug 27 Javascript
js手动播放图片实现图片轮播效果
Sep 17 Javascript
Vue动态修改网页标题的方法及遇到问题
Jun 09 Javascript
vue登录注册实例详解
Sep 14 Javascript
微信小程序实现电子签名并导出图片
May 27 Javascript
js实现小球在页面规定的区域运动
Jun 16 Javascript
openlayers4.6.5实现距离量测和面积量测
Sep 25 Javascript
TypeScript 使用 Tuple Union 声明函数重载
Apr 07 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
国王的咖啡这么大来头,名字的由来是什么
2021/03/03 咖啡文化
采用PHP函数memory_get_usage获取PHP内存清耗量的方法
2011/12/06 PHP
那些年一起学习的PHP(三)
2012/03/22 PHP
zend Framework中的Layout(模块化得布局)详解
2013/06/28 PHP
PHP获取一个字符串中间一部分字符的方法
2014/08/19 PHP
php生成图片缩略图功能示例
2017/02/22 PHP
php生成0~1随机小数的方法(必看)
2017/04/05 PHP
PHP laravel中的多对多关系实例详解
2017/06/07 PHP
php设计模式之备忘模式分析【星际争霸游戏案例】
2020/03/24 PHP
对字符串进行HTML编码和解码的JavaScript函数
2010/02/01 Javascript
JavaScript判断窗口是否最小化的代码(跨浏览器)
2010/08/01 Javascript
JS控制阿拉伯数字转为中文大写示例代码
2013/09/04 Javascript
用JS写的一个Ajax库(实例代码)
2016/08/06 Javascript
详解angularJs指令的3种绑定策略
2017/04/13 Javascript
JS实现瀑布流布局
2017/10/21 Javascript
vue检测对象和数组的变化分析
2018/06/30 Javascript
简单了解JavaScript作用域
2020/07/31 Javascript
vue 项目引入echarts 添加点击事件操作
2020/09/09 Javascript
OpenLayers3实现测量功能
2020/09/25 Javascript
跟老齐学Python之坑爹的字符编码
2014/09/28 Python
python抓取最新博客内容并生成Rss
2015/05/17 Python
python中zip和unzip数据的方法
2015/05/27 Python
详解Python发送邮件实例
2016/01/10 Python
python实现简单socket通信的方法
2016/04/19 Python
windows系统下Python环境的搭建(Aptana Studio)
2017/03/06 Python
python如何使用Redis构建分布式锁
2020/01/16 Python
详解CSS3中@media的实际使用
2015/08/04 HTML / CSS
浅谈CSS3动画的回调处理
2016/07/21 HTML / CSS
如何强制垃圾回收
2015/10/06 面试题
接口可以包含哪些成员
2012/09/30 面试题
党员培训思想汇报
2014/01/07 职场文书
职业道德模范事迹材料
2014/08/24 职场文书
2016大学迎新欢迎词
2015/09/29 职场文书
2016关于预防职务犯罪的心得体会
2016/01/21 职场文书
mysql 数据插入优化方法之concurrent_insert
2021/07/01 MySQL
搭建zabbix监控以及邮件报警的超级详细教学
2022/07/15 Servers