ホームページ  >  に質問  >  本文

javascript - Vue $watch 死循环问题

如果watch中的两个data变量相互调用了,会发生死循环。

watch:{
    'a':{
        handler:function(val,oldVal){
            if(this.b == 0){
                this.b = 1;
            }else{
                this.b = 0;
            }
        },
        deep:true
    },
    'b':{
        handler:function(val,oldVal){
            if(this.a == 0){
                this.a = 1;
            }else{
                this.a = 0;
            }
        },
        deep:true
    },
}

类似于这样,监听当a改变了去改变b,监听当b改变了去改变a
这样的话a和b会一直死循环下去,是在写全选、反选的时候遇到这个问题,当用户勾选全选后,再取消勾选一个条目,全选也会相对应取消勾选,这样就一直死循环下去了。
vue提供了相关的api解决这个问题吗?我在官网没有找到。

大家讲道理大家讲道理2749日前1025

全員に返信(2)返信します

  • 怪我咯

    怪我咯2017-04-10 18:12:22

    谢邀。
    虽然不知道你的实际开发需求是什么?但是你的程序在逻辑上就是你自己分析的死循环。
    watch是监控对象属性值的变化,即是你的a, b对应的值的变化了会回调触发这个监控函数下对应的键名表达式函数,函数会传入两个参数,一个是变化后的值,一个是变化前的值。
    如何解决这个问题?
    其实我也没想到好的办法,脑海里面一直是个死循环。要么就是数据单向,输入事件触发,但当前值的变化与否对实际结果不影响。a的变化结果不关心,只是关心它变化了会触发b。但是下一次a怎么判断它的变化又是问题了。

    还有一种就是固定判断零点值,b = 0b = 1两个极端条件,同理a也一样。

    a: function() {
        this.b == this.b == 0 ? 1 : (this.b == 1 ? 0 : 1);
    }

    前提条件是:a不能等于0或者1,否则又会触发死循环


    更新:

    实现全选功能

        <p id="app">
            <ol>
                <li>
                    <span><input type="checkbox" v-model="selectAll"></th></span>
                    <span align="left">全选</span>
                </li>
                <li v-for="answer in answers">
                    <span>
                        <input type="checkbox" v-model="selected" :value="answer.id" >
                    </span>
                    <span>{{ answer.name }}</span>
                </li>
            </ol>
        </p>
        <script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.0.5/vue.js"></script>
        <script>
            new Vue({
                el: '#app',
                data: {
                    answers: [ 
                        { "id": 1, "name": "A" },
                        { "id": 2, "name": "B" }, 
                        { "id": 3, "name": "C" }, 
                        { "id": 4, "name": "D" }
                    ],
                    selected: []
                },
                computed: {
                    selectAll: {
                        get: function () {
                            return this.answers ? this.selected.length == this.answers.length : false;
                        },
                        set: function (value) {
                            var selected = [];
    
                            if (value) {
                                this.answers.forEach(function (user) {
                                    selected.push(user.id);
                                });
                            }
    
                            this.selected = selected;
                        }
                    }
                }
            });
        </script>

    返事
    0
  • PHP中文网

    PHP中文网2017-04-10 18:12:22

    这种情况适合用v-on:change事件。

    返事
    0
  • キャンセル返事