组件双向属性绑定...三态复选框

时间:2019-03-06 17:28:55

标签: vue.js vue-component

我正在尝试构建一个三态复选框组件。 最初,该复选框的值为null,并由indeterminate复选框表示。 当用户单击不确定的复选框时,该值将变为true,然后单击false,然后再次为null。

到目前为止,这就是我所拥有的:

Vue.component('checkbox', {
        template: '<input type="checkbox" @change="change" class="checkbox-input">',
        props: ['currentSate'],
        mounted: function () {
            this.currentSate = null;
            this.$el.indeterminate = true
        },
        methods: {
            change: function () {
                if (this.currentSate == null) {
                    this.currentSate = true;
                    this.$el.checked = true;
                    this.$el.indeterminate = false;
                    return;
                }

                if (this.currentSate == true) {
                    this.currentSate = false
                    this.$el.checked = false;
                    this.$el.indeterminate = false;
                    return;
                }

                if (this.currentSate == false) {
                    this.currentSate = null;
                    this.$el.indeterminate = true;
                    return;
                }
                this.$emit('input', this.currentSate);
            }
        }
    });
        <checkbox v-bind:current-sate="chState"></checkbox>
                chState = {{chState}}

我得到的错误是:

  

避免直接更改prop,因为每当父组件重新渲染时,该值都会被覆盖。而是使用基于属性值的数据或计算属性。道具被突变:“ currentSate”

这怎么实现?

2 个答案:

答案 0 :(得分:1)

出现此错误时,简而言之,您需要发出所需的值,但让父级对其进行设置,以使它向下流回该属性

更多信息

您使用return !x; 向父级发送事件,父级将绑定到^[a-zA-Z0-9\.\/#-][a-zA-Z0-9\.\/# -]*[a-zA-Z0-9\.\/#-]$@emit的属性更改为您的情况,进而更新了子级。

:value的工作方式是输入子项的变化,  它会触发一个:currentSate事件,父级会收到该事件并修改绑定的v-model,然后回溯到子级。

看起来有些乏味,但最终消除了一系列设计问题。

解决方案

因此,就您而言,您不应修改@input。只需:value新值,然后修改currentSate。让父级修改@emit绑定到currentSate的内容,这将修改属性data

我建议您使用:currentSate代替currentSate来遵循Vue约定。如果您发出value并收到currentSate,则input将立即可用。

对于Tri State Box

您可以听“单击”,然后打开属性“ currentSate”的值。只需根据当前值发出下一个值。您仍然需要让父级更新绑定值。

value

以下是监听事件并更新bound属性的示例:

v-model

现在,如果您发出onClick(value){ switch(this.currentSate){ case null: this.$emit('input', true); break; case true: this.$emit('input', false); break; case false: this.$emit('input', null); break; } } 并绑定到<checkbox v-bind:current-sate="chState" @input='chState=$event'></checkbox> 而不是input,则可以这样做:

:value

currentSate适用于以下惯例:将值作为<checkbox v-model="chState"></checkbox> 发出,并将属性作为v-model接受。

答案 1 :(得分:0)

没有一个答案是完整的 所以就在这里。

Vue.component('checkbox', {
        template: '<input type="checkbox" @change="change" class="checkbox-input">',
        props: ['value'],
        mounted: function () {
            this.value = null;
            this.$el.indeterminate = true
        },
        methods: {
            change: function () {
                if (this.value == null) {
                    this.$emit('input', true);
                    return;
                }

                if (this.value == true) {
                    this.$emit('input', false);
                    return;
                }

                if (this.value == false) {
                    this.$el.indeterminate = true;
                    this.$emit('input', null);

                    return;
                }
            }
        }
    });

    var myApp = new Vue(
        {
            el: '#app',
            data: {
                chState: null,
            }
        });
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
 <checkbox v-model="chState"></checkbox>
        chState = {{chState}}
</div>