我可以更改绑定到VueJS中另一个变量的分量prop变量吗

时间:2019-02-22 14:20:27

标签: javascript vue.js components

我开始学习vuejs,并希望使用vue中的组件创建一个简单的“ like”项目。我做了两个按钮(喜欢和不喜欢),每个按钮都有单独的计数器。到现在为止,一切都还不错。 现在,我想在下面显示这些计数器的总和。为此,我需要在组件外部将这两个变量彼此相邻,因此我尝试将其值与外部变量绑定。但是外部变量没有改变!并在控制台中说:

  

[Vue警告]:避免直接更改道具,因为每当父组件重新渲染时,该值就会被覆盖。而是使用基于属性值的数据或计算属性。道具被突变:“ lval”   在--->

中找到

查看我的代码:

Vue.component('like',{
    template: '#like' ,
    props: ['lval','lname','lstep','lclass'],
    methods:{
        changeCounter : function(step){
            this.lval += parseInt(step);
        }
    }
});
new Vue({
    el: '#app',
    data:{
        counterlike: 0,
        counterdislike: 0
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
        <like lname="Like" lstep="1" :lval="counterlike" lclass="btn-success"></like>
        <like lname="Dislike" lstep="-1" :lval="counterdislike" lclass="btn-danger"></like>
        <br>
        {{ counterlike + counterdislike }}
    </div>

    <template id="like">
        <button :class="['btn',lclass]" @click="changeCounter(lstep)" >{{ lname + ' ' + lval }}</button>
    </template>

3 个答案:

答案 0 :(得分:0)

道具不能直接突变是有原因的,这种方式使信息具有单向流动,从父母到孩子,而不是相反。

See: One Way Data Flow

答案 1 :(得分:0)

True 不能实现双向绑定,但是子级可以向父级发出带有所需信息的事件,而后者可以更新绑定变量。

从2.3.0版本开始,Vue具有特殊的.sync modifier来做到这一点,这是使用.sync修饰符修改的代码段。请注意,changeCounter方法不会直接更改lval,而是会发出事件。

这里

Vue.config.productionTip = false;
Vue.component('like', {
  template: '#like',
  props: ['lval', 'lname', 'lstep', 'lclass'],
  methods: {
    changeCounter: function(step) {
      const newlval = this.lval + parseInt(step);
      this.$emit('update:lval', newlval);
    }
  }
});
new Vue({
  el: '#app',
  data: {
    counterlike: 0,
    counterdislike: 0
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <like lname="Like" lstep="1" :lval.sync="counterlike" lclass="btn-success"></like>
  <like lname="Dislike" lstep="-1" :lval.sync="counterdislike" lclass="btn-danger"></like>
  <br> {{ counterlike + counterdislike }}
</div>

<template id="like">
  <button :class="['btn',lclass]" @click="changeCounter(lstep)" >{{ lname + ' ' + lval }}</button>
</template>

答案 2 :(得分:0)

根据您的情况,您可以简单地使用.sync修饰符来避免直接更改道具。同步修饰符表示您的道具接收者组件(子代)从父级接收道具数据,并在父级必须更改传递的值时生成一个事件。 父组件应将prop与'.sync'修饰符绑定,这意味着对带有更新的子事件进行自动订阅。 您可以阅读here

的更多信息

这样,您的代码可以正常工作

Vue.component('like',{
    template: '#like' ,
    props: ['lval','lname','lstep','lclass'],
    methods:{
        changeCounter : function(step){
            this.$emit('update:lval', this.lval + parseInt(step));
        }
    }
});
new Vue({
    el: '#app',
    data:{
        counterlike: 0,
        counterdislike: 0
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
        <like lname="Like" lstep="1" :lval.sync="counterlike" lclass="btn-success"></like>
        <like lname="Dislike" lstep="-1" :lval.sync="counterdislike" lclass="btn-danger"></like>
        <br>
        {{ counterlike + counterdislike }}
    </div>

    <template id="like">
        <button :class="['btn',lclass]" @click="changeCounter(lstep)" >{{ lname + ' ' + lval }}</button>
    </template>