【问题标题】:Can i change component prop variable binded to another variable in VueJS我可以更改绑定到 VueJS 中另一个变量的组件道具变量吗
【发布时间】:2019-07-16 16:01:19
【问题描述】:

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

[Vue 警告]:避免直接改变 prop,因为每当父组件重新渲染时,该值都会被覆盖。相反,使用基于道具值的数据或计算属性。正在变异的道具:“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>

【问题讨论】:

    标签: javascript vue.js components


    【解决方案1】:

    对于您的情况,您可以简单地使用.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>

    【讨论】:

      【解决方案2】:

      真正的无法实现双向绑定,但子级可以向父级发出带有所需信息的事件,后者可以更新绑定变量。

      从 2.3.0 开始,Vue 有一个特殊的 .sync modifier 可以做到这一点,这是你使用 .sync 修饰符修改后的 sn-p。请注意,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>

      【讨论】:

        【解决方案3】:

        props 不能直接变异是有原因的,这样信息是单向流动的,从父级到子级,而不是相反。

        See: One Way Data Flow

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-10-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多