因为vue2.0去除了父子组件的双向数据绑定,所以在子组件是不允许修改父组件的属性的,控制台会报如下错误:
[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: "onlyContent"
解决办法
在子组件data中定义一个父组件传递过来的副本,再把该副本利用this.$emit("event","value")传回父组件,父组件利用自定义事件接受传回的值
子组件
<
template
>
<
div
class=
"ratingselect"
>
<
div
class=
"rating-type"
>
<
span @
click=
"select(2,$event)"
class=
"block positive" :
class=
"{'active':selecttype===2}"
>
{{desc.all}}
<
span
class=
"count"
>47
</
span
>
</
span
>
<
span @
click=
"select(0,$event)"
class=
"block positive" :
class=
"{'active':selecttype===0}"
>
{{desc.positive}}
<
span
class=
"count"
>47
</
span
>
</
span
>
<
span @
click=
"select(1,$event)"
class=
"block negative" :
class=
"{'active':selecttype===1}"
>
{{desc.negative}}
<
span
class=
"count"
>47
</
span
>
</
span
>
</
div
>
<
div @
click=
"toggleContent()"
class=
"switch" :
class=
"{'on':onlycontent}"
>
<
span
class=
"icon-check_circle"
></
span
>
<
span
class=
"text"
>只看有内容的评价
</
span
>
</
div
>
</
div
>
</
template
>
<
script
>
const POSITIVE =
0;
const NEGATIVE =
1;
const ALL =
2;
export
default {
//组件要维护的部分
props:{
//接收ratings,默认返回数组
ratings:{
type:
Array,
default(){
return [];
}
},
//接收评论类型,默认选中的是‘全部’
selectType:{
type:
Number,
default:ALL
},
//接收是否看有内容的评价状态,默认false
onlyContent:{
type:
Boolean,
default:
false
},
//接收评论类型
desc:{
type:
Object,
default(){
return {
all:
'全部',
positive:
'满意',
negative:
'不满意'
};
}
}
},
data(){
return{
selecttype:
this.
selectType,
onlycontent:
this.
onlyContent,
}
},
methods: {
select(
type,
event){
if(!
event.
_constructed){
return;
}
/*
由于子组件改了selectType但是父组件不知道,
所以用事件广播来使父组件知道
*/
this.
selecttype=type;
this.
$emit(
'selectchange',
this.
selecttype);
},
toggleContent(){
this.
onlycontent=!
this.
onlycontent;
this.
$emit(
'onlycontentChange',
this.
onlycontent);
}
}
}
</
script
>
父组件
<
template
>
<
transition
name=
"move"
>
<
div
class=
"food"
v-show=
"showFlag"
ref=
"foodDom"
>
<
div
class=
"food-content"
>
<
div
class=
"img-header"
>
<
img :
src=
"food.image"
>
<
div
class=
"back" @
click=
"hide()"
>
<
i
class=
"icon-arrow_lift"
></
i
>
</
div
>
</
div
>
<
div
class=
"content"
>
<
h1
class=
"title"
>{{food.name}}
</
h1
>
<
div
class=
"detail"
>
<
span
class=
"sell-count"
>月售{{food.sellCount}}
</
span
>
<
span
class=
"rating"
>好评率{{food.rating}}%
</
span
>
</
div
>
<
div
class=
"price"
>
<
span
class=
"now"
>¥{{food.price}}
</
span
>
<
span
class=
"old"
v-show=
"food.oldPrice"
>¥{{food.oldPrice}}
</
span
>
</
div
>
<
div
class=
"cartcontrol-wrapper"
>
<
v-cartcontrol :
food=
"food"
></
v-cartcontrol
>
</
div
>
<
transition
name=
"fade"
>
<
div @
click=
"addFirst($event)"
class=
"addBuy"
v-show=
"!food.count || food.count === 0"
>加入购物车
</
div
>
</
transition
>
</
div
>
<
div
class=
"spilt"
v-show=
"food.info"
></
div
>
<
div
class=
"info"
v-show=
"food.info"
>
<
h1
class=
"title"
>商品介绍
</
h1
>
<
p
class=
"text"
>{{food.info}}
</
p
>
</
div
>
<
div
class=
"spilt"
v-show=
"food.info"
></
div
>
<
div
class=
"rating"
>
<
h1
class=
"title"
>商品评价
</
h1
>
<
v-rating @
onlycontentChange=
"changeOnlycontent" @
selectchange=
"changeSelect" :
selectType=
"selectType" :
onlyContent=
"onlyContent" :
desc=
"desc" :
ratings=
"food.ratings"
></
v-rating
>
</
div
>
</
div
>
</
div
>
</
transition
>
</
template
>
<
script
>
import
Vue
from
'vue'
import
BScroll
from
'better-scroll'
import
Cartcontrol
from
'../cartcontrol/cartcontrol.vue'
import
Rating
from
'../rating/rating.vue'
const POSITIVE =
0;
const NEGATIVE =
1;
const ALL =
2;
export
default {
data(){
return{
showFlag:
false,
selectType:ALL,
onlyContent:
false,
desc:{
all:
'全部',
positive:
'推荐',
negative:
'吐槽'
}
}
},
props:{
food:{
type:
Object
}
},
components:{
'v-cartcontrol':Cartcontrol,
'v-rating':Rating
},
computed:{
},
methods:{
show(){
this.
showFlag =
true;
//商品详情组件时初始化状态
this.
selectType=ALL;
this.
onlyContent=
false;
this.
$nextTick(()
=>{
if(!
this.
scroll){
this.
scroll =
new
BScroll(
this.
$refs.
foodDom,{click:
true})
}
else{
this.
scroll.
refresh();
}
});
},
hide(){
this.
showFlag =
false;
},
addFirst(
event){
if(!
event.
_constructed){
return;
}
Vue.
set(
this.
food,
'count',
1);
},
changeSelect(
val){
this.
selectType=val;
},
changeOnlycontent(
val){
this.
onlyContent=val;
}
}
}
</
script
>
作者:BrotherWy
链接:https://www.jianshu.com/p/751440d84d7a
來源:简书