Vue 改變數組中對象的屬性不從新渲染View的解決方案

Vue 改變數組中對象的屬性不從新渲染View的解決方案javascript

   在解決問題以前,咱們先來了解下 vue響應性原理: Vue最顯著的一個功能是響應系統-- 模型只是一個普通對象,修改對象則會更新視圖。
受到javascript的限制,Vue不能檢測到對象屬性的添加或刪除,由於vue在初始化實列時將屬性轉爲getter/setter,因此屬性必須在data對象上才能讓vue轉換它。
可是vue能夠使用 Vue.set(object, key, value)方法將響應屬性添加到嵌套的對象上:以下代碼:html

Vue.set(obj, '_isHover', true);

或者能夠使用vm.$set的實列方法,也是Vue.set方法的別名:vue

this.$set(obj, '_isHover', false);

問題: 頁面上多個item項, 當我鼠標移動上去的時候,我想在該數組中的對象添加一個屬性 isHover=true, 當鼠標移出的時候,我想讓該屬性變爲 isHover=false,而後但願改變對象的屬性的時候讓其從新渲染view層,從新執行rowClasses方法,而後該方法會判斷 isHover是否等於true,若是爲true的話,讓其增長一個類名。
代碼以下:java

<!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>

查看效果git

能夠看到鼠標移動上去的時候 沒有效果。github

解決的方案以下:數組

1. 使用 Object.assignapp

鼠標移動上去的時候 代碼能夠改爲以下:this

this.$data.items[index]._isHover = true;
this.$data.items = Object.assign({}, this.$data.items);

鼠標移出的時候,代碼改爲以下:spa

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>

查看效果

相關文章
相關標籤/搜索