简体   繁体   English

我可以更改绑定到 VueJS 中另一个变量的组件道具变量吗

[英]Can i change component prop variable binded to another variable in VueJS

I started learning vuejs and wanted to make a simple "like" project using components in vue.我开始学习 vuejs 并想使用 vue 中的组件制作一个简单的“喜欢”项目。 I made two button (like and dislike) that every one has separate counter.我做了两个按钮(喜欢和不喜欢),每个按钮都有单独的计数器。 Until now everything was OK.直到现在一切都很好。 Now, I want show sum of these counters in under.现在,我想在下面显示这些计数器的总和。 for this I need these 2 variables next to each other outside the component so I try to bind their values with external variables.But external variables didn't change!为此,我需要在组件外部将这两个变量彼此相邻,因此我尝试将它们的值与外部变量绑定。但是外部变量没有改变! and also said in the console:并且还在控制台中说:

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. [Vue 警告]:避免直接改变 prop,因为每当父组件重新渲染时,该值都会被覆盖。 Instead, use a data or computed property based on the prop's value.相反,使用基于道具值的数据或计算属性。 Prop being mutated: "lval" found in --->正在变异的道具:在 ---> 中找到“lval”

See my Code:请参阅我的代码:

 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>

There is a reason why props can't be mutated directly, this way the information has one-way flow, from parent to child and not the other way around. props 不能直接变异是有原因的,这样信息是单向流动的,从父母到孩子,而不是相反。

See: One Way Data Flow 请参阅:单向数据流

True two-way bindings can't be achieved, but the child can emit an event with needed info to the parent, and the latter could update bound variable.无法实现真正​​的双向绑定,但子级可以向父级发出带有所需信息的事件,后者可以更新绑定变量。

Since 2.3.0 Vue has a special .sync modifier to do just that, and here is your modified snippet using .sync modifier.从 2.3.0 开始,Vue 有一个特殊的.sync修饰符来做到这一点,这里是你使用.sync修饰符的修改片段。 Note, that changeCounter method doesn't change lval directly, but emits an event.请注意, changeCounter方法不会直接更改lval ,而是会发出一个事件。

Here这里

 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>

For your situation you can simply use .sync modifier to avoid mutating props directly.对于您的情况,您可以简单地使用.sync修饰符来避免直接改变道具。 Sync modifier means your prop receiver component (child) receives props data from parent and generates an event when parent must change passed value.同步修饰符意味着您的道具接收器组件(子)从父级接收道具数据并在父级必须更改传递的值时生成一个事件。 And parent component should bind prop with '.sync' modifier that means auto subscription on child event with update.并且父组件应该将 prop 与 '.sync' 修饰符绑定,这意味着通过更新自动订阅子事件。 More info you can read here您可以在此处阅读更多信息

This way your code will work fine这样你的代码就可以正常工作

 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM