从vue1.0升级至2.0之后 prop的.sync被去除 因此直接在子组件修改父组件的值是会报错的 目的是为了阻止子组件影响父组件的数据
1)首先将父组件的数据传递到子组件中,data :绑定
food.vue(父组件中)
data () {
return {
showFlag: false,
selectType: ALL,
onlyContent: true, //先设置组件一开始显示有内容的评价
desc: { //desc做了改变
all: '全部',
positive: '推荐',
negative: '吐槽'
}
};
},
<ratingselect :select-type="selectType" :only-content="onlyContent" :desc="desc" :ratings="food.ratings"></ratingselect>
2)子组件接收数据,修改数据,然后设置派发事件将修改后的数据派发的父组件
ratingSelect.vue(子组件中),在子组件中除了用props接收父子间的数据之外,还要在data中定义两个变量,将props中接收到的值赋值给这两个新变量,之后在子组件中改变的都是这两个新的变量
props: {
ratings: {
type: Array,
default() {
return [];
}
},
selectType: { //全部,满意,不满意
type: Number,
default: ALL //默认情况时ALL,值等于2
},
onlyContent: { //只看有内容的评价还是所有的评价
type: Boolean,
default: false //设置为可以看到所有的评价
},
desc: { //描述
type: Object,
default() { //默认desc是这三种,在商品详情页的时候传入推荐或者吐槽
return {
all: '全部',
positive: '满意',
negative: '不满意'
};
}
}
},
data() {
return {
sType: this.selectType,
oContent: this.onlyContent
}
},
<div class="ratingselect">
<div class="rating-type" border-1px>
<span class="block positive" @click="select(2,$event)" :class="{'active':sType === 2}">{{desc.all}}<span class="count">47</span> </span>
<span class="block positive" @click="select(0,$event)" :class="{'active':sType === 0}">{{desc.positive}}<span class="count">40</span></span>
<span class="block negative" @click="select(1,$event)" :class="{'active':sType === 1}">{{desc.negative}}<span class="count">47</span></span>
</div>
<div @click="toggleContent($event)" class="switch" :class="{'on':oContent}">
<span class="icon-check_circle"></span>
<span class="text">只看有内容的评价</span>
</div>
</div>
在click事件中改变自定义变量的值,并利用$emit派发事件将新值传入
methods: {
select (type, event) { //点击的时候外层是有一个BScroll的,所以要传递event阻止默认点击
if (!event._constructed) { //浏览器直接return掉,去掉自带click事件的点击
return;
}
//将this.selectType设置成传入的参数,而不是food传过来的初始化的值,之后样式就可以随着点击改变了
this.sType = type;
//派发事件通知父组件food.vue selectType的改变,将type值传出去
console.log('ratingselect.vue ' + type);
//this.$emit('se-type', type);
this.$emit('increment', 'selectType', this.sType); //selectType要跟food.vue中data定义的同名
},
toggleContent (event) {
if (!event._constructed) { //浏览器直接return掉,去掉自带click事件的点击
return;
}
this.oContent = !this.oContent;
console.log('ratingselect.vue ' + this.oContent);
// this.$emit('toggle-content', this.oContent);
this.$emit('increment', 'onlyContent', this.oContent);//onlyContent要跟food.vue中data定义的同名
}
},
3)父组件food.vue监听函数,要写在methods中
incrementTotal(type, data) {
this[type] = data;
this.$nextTick(() => {
this.scroll.refresh();
});
在子组件中绑定函数 @increment="incrementTotal"
<ratingselect @increment="incrementTotal" :select-type="selectType" :only-content="onlyContent" :desc="desc" :ratings="food.ratings"></ratingselect>
4)实现点击不同选项时评价列表的刷新,在父组件food.vue中添加
needShow(type, text) {
// console.log('this.selectType: ' + this.selectType + ' type: ' + type + ' out ' + text);
if (this.onlyContent && !text) {
return false;
}
if (this.selectType === ALL) {
return true;
} else {
//console.log('this.selectType: ' + this.selectType + 'type: ' + type + ' in ' + text);
return type === this.selectType;
}
},
并将needShow()函数添加在DOM中li中的v-show条件下
<div class="rating-wrapper"> <!-- 评价列表-->
<ul v-show="food.ratings && food.ratings.length">
<li v-show="needShow(rating.rateType, rating.text)" v-for="rating in food.ratings" :key="rating.id" class="rating-item border-1px">
<div class="user">
<span class="name">{{rating.username}}</span>
<img class="avatar" height="12" width="12" :src="rating.avatar" alt="">
</div>
<div class="time">{{rating.rateTime | formatDate}}</div>
<p class="text">
<span :class="{'icon-thumb_up':rating.rateType === 0, 'icon-thumb_down':rating.rateType === 1}"></span>{{rating.text}}
</p>
</li>
</ul>
<div class="no-ratings" v-show="!food.ratings || !food.ratings.length">暂无评价</div>
</div>