详解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 相关文章推荐
使用按钮控制以何种方式打开新窗口的属性介绍
Dec 17 Javascript
JQuery入门—JQuery程序的代码风格详细介绍
Jan 03 Javascript
js事件监听器用法实例详解
Jun 01 Javascript
node.js读取文件到字符串的方法
Jun 29 Javascript
jQuery中使用animate自定义动画的方法
May 29 Javascript
ES6新特性之Symbol类型用法分析
Mar 31 Javascript
vue组件中点击按钮后修改输入框的状态实例代码
Apr 14 Javascript
JS写XSS cookie stealer来窃取密码的步骤详解
Nov 20 Javascript
angular中子控制器向父控制器传值的实例
Oct 08 Javascript
在layui中layer弹出层点击事件无效的解决方法
Sep 05 Javascript
解决vue项目刷新后,导航菜单高亮显示的位置不对问题
Nov 01 Javascript
JS document内容及样式操作完整示例
Jan 14 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
zend framework配置操作数据库实例分析
2012/12/06 PHP
关于尾递归的使用详解
2013/05/02 PHP
php版银联支付接口开发简明教程
2016/10/14 PHP
laravel框架使用FormRequest进行表单验证,验证异常返回JSON操作示例
2020/02/18 PHP
ext读取两种结构的xml的代码
2008/11/05 Javascript
JSON与XML优缺点对比分析
2015/07/17 Javascript
JQ实现新浪游戏首页幻灯片
2015/07/29 Javascript
利用JavaScript阻止表单提交的两种方法
2016/08/11 Javascript
JavaScript中的子窗口与父窗口的互相调用问题
2017/02/08 Javascript
解析Vue 2.5的Diff算法
2017/11/28 Javascript
jQuery实现鼠标移入移出事件切换功能示例
2018/09/06 jQuery
详解如何在vscode里面调试js和node.js的方法步骤
2018/12/24 Javascript
Layui弹出层 加载 做编辑页面的方法
2019/09/16 Javascript
基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能
2019/11/12 Javascript
浅谈使用nodejs搭建web服务器的过程
2020/07/20 NodeJs
Python基于smtplib实现异步发送邮件服务
2015/05/28 Python
Python实现字典的遍历与排序功能示例
2017/12/23 Python
在PyCharm下打包*.py程序成.exe的方法
2018/11/29 Python
安装Pycharm2019以及配置anconda教程的方法步骤
2019/11/11 Python
python列表推导和生成器表达式知识点总结
2020/01/10 Python
python的sys.path模块路径添加方式
2020/03/09 Python
解决pycharm编辑区显示yaml文件层级结构遇中文乱码问题
2020/04/27 Python
IntelliJ 中配置 Anaconda的过程图解
2020/06/01 Python
园艺师求职信
2014/04/27 职场文书
5s推行计划书
2014/05/06 职场文书
护理专业求职信
2014/06/15 职场文书
居委会四风问题个人对照检查材料
2014/09/25 职场文书
2014年创卫工作总结
2014/11/24 职场文书
投标单位介绍信
2015/05/05 职场文书
社区法制宣传日活动总结
2015/05/05 职场文书
幼儿园教学工作总结2015
2015/05/12 职场文书
创业计划书之烤红薯
2019/09/26 职场文书
Python 多线程之threading 模块的使用
2021/04/14 Python
.Net Core导入千万级数据至Mysql的步骤
2021/05/24 MySQL
Pandas加速代码之避免使用for循环
2021/05/30 Python
java高级用法JNA强大的Memory和Pointer
2022/04/19 Java/Android