vue2.0 饿了么学习笔记(13)子组件改变父组件的值

从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>

猜你喜欢

转载自blog.csdn.net/qq_22317389/article/details/80405425