vue报错: [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated: “***”
翻译:
避免直接改变一个组件中的prop值,因为每当父组件重新渲染时,该prop值都将被覆盖。应在组件中使用基于这个prop值的data或computed属性。
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。
https://cn.vuejs.org/v2/guide/components-props.html#单向数据流
在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题。
取而代之的是,在父组件中对传递给子组件的prop使用.sync修饰符,子组件改变prop后,以 this.$emit(‘update: propName’, newvalue)的模式触发事件,告诉父组件我已经更改这个prop值了。
https://cn.vuejs.org/v2/guide/components-custom-events.html#sync-修饰符
在父组件中对传递给子组件的prop使用.sync修饰符:
<parent-component v-bind:select-type.sync="selectType"></parent-component>
在子组件js中:
props: {
selectType: {
type: Number,
default: 2
}
},
methods: {
select (type, event) {
this.selectType = type;
this.$emit('update:selectType', type);
}
}
有两种常见的试图改变一个 prop 的情形:
- 这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
- 这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
注意
在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。
选项卡切换时被点击的项高亮:
html
<div class="rating-type border-1px">
<span
class="block positive"
:class="{'active': selectedType===2}"
@click="select(2, $event)"
>{{desc.all}}<span class="count">57</span></span>
<span
class="block positive"
:class="{'active': selectedType===0}"
@click="select(0, $event)"
>{{desc.positive}}<span class="count">40</span> </span>
<span
class="block negative"
:class="{'active': selectedType===1}"
@click="select(1, $event)"
>{{desc.negative}}<span class="count">10</span> </span>
</div>
javascript
// 选择类型默认为ALL
const ALL = 2;
props: {
selectType: {
type: Number,
default: ALL
}
},
data: function () {
return {
selectedType: this.selectType
}
},
methods: {
select (type, event) {
if (!event._constructed) {
return;
}
this.selectedType = type;
}
}