之前在介绍过vue computed原理分析: vue computed原理分析,今天来看一个我遇到的关于computed比较奇怪的问题:

    vue computed使用注意

    需求比较简单,一个页面上有一个勾选框,还有一个数组(列表,可以通过按钮添加),需要数组中有内容并且是选中状态提交按钮才会点亮。代码如下:

    1. <!--html-->
    2. <div id='app'>
    3.     <div>
    4.         <p>至少添加一个项目且勾选才能提交</p>
    5.         <div>
    6.             <input type='text' v-model='value' placeholder='请输入项目内容' />
    7.             <button @click='addItem'>添加项目</button>
    8.         </div>
    9.         <ul>
    10.             <li v-for='item in list'>{{item}}</li>
    11.         </ul>
    12.         <label>
    13.             <input type='checkbox' v-model='check'/>
    14.             <span>是否勾选</span>
    15.         </label>
    16.         <div class='btn' :class='{active:canSubmit}'>提交</div>
    17.     </div>
    18. </div>
    19. <!--js-->
    20. const app = new Vue({
    21.     el: '#app',
    22.     data: {
    23.         check: false, //是否选中
    24.         list: [],
    25.         value: '',
    26.     },
    27.     computed: {
    28.         canSubmit: function() {
    29.             console.log('触发执行canSubmit');
    30.             return this.list.length && this.check;
    31.         }
    32.     },
    33.     mounted: function() {
    34.     },
    35.     methods: {
    36.         addItem: function() { //增加项目
    37.             if(this.value) {
    38.                 this.list.push(this.value);
    39.                 this.value = '';
    40.             }
    41.         }
    42.     }
    43. })

    其中按钮点亮用的是一个computed:canSubmit,根据list和check判断:return this.list.length && this.check;

    因为computed中同时关联了check和list,那么按理说check或list发生变化的时候,canSubmit应该变化的,但是看上图可以发现,当list为空的时候(未添加),触发check的时候,canSubmit并无任何变化!!

    虽然这个小细节并不影响整体的功能,但是我们仔细思考一下,为什么当list为空的时候,改变check无法改变canSubmit呢?

    问题分析

    这个其实和computed的实现原理有关,不太熟悉的朋友,可以点进文章开头的链接去看看原理。computed之所有可以关联多个变量,是因为执行computed方法的时候,内部调用了data上的对象,(list,check),执行了getter,才会让Dep和Watcher关联上。

    我们的方法是return this.list.length && this.check;第一个条件为false,那么第二个条件自然也就不执行了,因此check和canSubmit之间没有关联关系。只有list和canSubmit的关联关系。所以当list没有数据的时候,修改check并不会改变canSubmit。

    但是当list有数据的时候,canSubmit会执行,此时的this.list.length得到的true,会执行到this.check,因此此时check又和canSubmit恢复了绑定关系。

    问题规避

    通过上面的分析可以得到,如果变量直接和&&,||之类一起执行的时候,可能导致不执行,因此我们要确保变量都执行了getter:

    1. computed: {
    2.     canSubmit: function() {
    3.         let len=this.list.length,
    4.             _check=this.check;
    5.         return len && _check;
    6.     }
    7. },

    改成上面那样,无论list有没有数据,都可以取保执行了this.check,那么check就和canSubmit就可以保持关联了。

    回到顶部
    我要评论

    所有评论

      相关文章