项目总结:vue(2),看这篇足矣了

124 阅读8分钟

目录

一、food组件-商品部分

1. 概述

2. 布居

3. 实现

(1)添加头图

(2)使用声明式调用food(未采用)

(3)注册api组件

(4)实现food 组件内部滚动

(5)使用sticky组件

(6)在商品详情页进行购物

二、food组件-评价部分

1. 布局

2. 实现

(1)显示整个评论列表

(2)时间部分

(3)评价过滤功能

三、food组件-rating-select组件

1. 布局

2. 实现

(1)rating-select组件接收数据

(2)rating-select组件使用

(3)添加点击事件

(4)控制列表显示变化


一、food组件-商品部分

=================

1. 概述


在商品页面中点击某一个商品,可以跳到商品详情页查看详情,包括:商品图片、名称价格、商品评价、加入购物车。该组件为全屏弹层组件,如果单纯作为goods的子组件调用会出现不能全屏显示的问题。因此将其注册为create-API模块,让good组件动态挂载到body下。(这样就可以使用fixed全屏布局以及层级的z-index来控制是否盖住下面的header部分。)(原因:food是fixed布局,外部有一个transform,fixed布局会受到transform影响,因此对于全屏类弹层组件,组件的样式很容易受到父元素影响,(fixed布局是全屏类的))同样的,该页面也需要控制shop-cart-sticky购物车组件显隐。

评论部分有两个维度实现过滤:首先可以查看评价类型(全部、推荐、吐槽)还有“只看有内容的评价”,将其该部分设置为rating-select组件,接收props(ratings是个数组(通过ratings可以计算各部分的评价个数);selectType是选择类型(有三种类型,定义三种常量POSITIVE、NEGATIVE、ALL)使用常量增加可读性;onlycontent是否有内容;desc描述(对象默认描述:all:"全部" positive:“满意” negative:“不满意”) )外部可以传入标签,从而实现复用。在food中添加计算属性computedRatings,定义数组并遍历将符合的ratings放入(当选中所有时push(rating)或者当前选择类型和这条评价类型相同,也push(rating))从而按情况显示ratings.

(在rating-select中的每个选项添加点击事件select,toggle 。由于selectType是传递过来的props不能直接修改,因此把这个props的值派发到父组件food,让后让父组件做修改,响应式更新数据,通过props再影响子组件。)

2. 布居


当点击某一商品时点击可以查看详情,主要分为:头部图片+商品购物+商品信息+评价

商品评价可以有选项分类,有全部、推荐、吐槽,并且有一个按钮可以只看有内容的评价

二期:goods组件需要基于API实现

<transition name="move" @after-leave="afterLeave">

<cart-control @add="addFood" :food="food">

加入购物车

需要接收food这个props,需要根据不同的food渲染不同内容,开始是隐藏的,通过通过使用visible控制显隐,其中的对应左滑的过渡动画,内部使用cube-scroll组件实现滚动.

3. 实现


(1)添加头图

使用height:0 padding-top:100%的方式,让图片可以达到等比效果

(2)使用声明式调用food(未采用)

即在goods组件中引入food组件。使用food组加需要传入:food="selectedFood",在goods组件中,当选中列表的一项时,添加点击事件selectFood(food),并实现方法(将food赋值给selectedFood)。在data中声明一个当前选中的商品selectedFood.并且给添加一个ref="food"

selectFood(food){

this.selectedFood = food

this.$refs.food.show()

}

发现效果是在下面区域显示整个food组件而没有遮盖头部部分。

**原因:**food是fixed布局,外部有一个transform,fixed布局会受到transform影响,因此对于全屏类弹层组件,组件的样式很容易受到父元素影响,(fixed布局是全屏类的)

**解决方法:**使用create-API模块,让good组件动态挂载到body下。这样就可以使用fixed全屏布局以及层级的z-index来控制是否盖住下面的header部分。

(3)注册api组件

定义私有方法_showFood(),当选择的food变化了,selectedFood响应式变化

selectFood(food) {

this.selectedFood = food

this._showFood()

this._showShopCartSticky()

},

_showFood() {

this.foodComp = this.foodComp || this.$createFood({

$props: {

food: 'selectedFood'

},

$events: {

leave: () => {

this._hideShopCartList()

},

add: (el) => {

this.shopCartStickyComp.drop(el)

}

}

})

this.foodComp.show()

},

(4)实现food 组件内部滚动

scroll每次需要初始化,在food组件中添加created

const EVENT_SHOW = 'show'

created() {

this.$on(EVENT_SHOW, () => {

this.$nextTick(() => {

this.$refs.scroll.refresh()

})

})

},

(5)使用sticky组件

在goods组件中,打开food组件时,同时要将shop-cart-sticky组件显示出来。同时定义showSopCartSticky()方法

selectFood(food) {

this.selectedFood = food

this._showFood()

this._showShopCartSticky()

},

_showShopCartSticky() {

this.shopCartStickyComp = this.shopCartStickyComp || this.$createShopCartSticky({

$props: {

selectFoods: 'selectFoods',

deliveryPrice: this.seller.deliveryPrice,

minPrice: this.seller.minPrice,

fold: true

}

})

this.shopCartStickyComp.show()

},

_hideShopCartSticky() {

this.shopCartStickyComp.hide()

}

当动画结束时隐藏sticky组件,在food组件添加过渡钩子函数after-leave=afterLeave

afterLeave() {

this.$emit(EVENT_LEAVE) //leave

},

并且在goods组件中的——showFood中添加event(hideShopCartSticky)

_showFood() {

this.foodComp = this.foodComp || this.$createFood({

$props: {

food: 'selectedFood'

},

$events: {

leave: () => {

this._hideShopCartSticky()

},

add: (el) => {

this.shopCartStickyComp.drop(el)

}

}

})

this.foodComp.show()

},

(6)在商品详情页进行购物

比之前的cart-control多一步,在没有购买时会显示“加入购物车”,

实现:使用两层,一层是使用cat-control组件,另一层是一个按钮,并且使用组件包裹,驱动动画的变化,通过food.count控制显隐,当count是0或者undefined,就是显示的,否则相反。都是用绝对定位,让“加入购物车”部分盖住cart-control

<cart-control @add="addFood" :food="food">

加入购物车

并且在“加入购物车”添加addFirst方法,(没有count时设置为1)点击按钮驱动外层的shop-cart-sticky组件,因此需要派发EVENT_ADD;在cart-control添加addFood方法(事件向父组件传递,food组件的父组件是goods,里面含有shopCartStickyComp,它的drop()方法才是真正调用小球动画的,因此事件需要一层层派发)

addFirst(event) {

this.$set(this.food, 'count', 1)

this.$emit(EVENT_ADD, event.target)

},

addFood(target) {

this.$emit(EVENT_ADD, target)

},

这是在goods中监听add方法完成动画

_showFood() {

this.foodComp = this.foodComp || this.$createFood({

$props: {

food: 'selectedFood'

},

$events: {

leave: () => {

this._hideShopCartSticky()

},

add: (el) => {

this.shopCartStickyComp.drop(el)

}

}

})

this.foodComp.show()

},

二、food组件-评价部分

=================

1. 布局


除了有对评价的显示,还有对评价的过滤,可以对评价列表进行切换。

商品评价

  • {{rating.username}}

    {{format(rating.rateTime)}}

暂无评价

2. 实现


(1)显示整个评论列表

ratings使用计算属性(简化书写)

    v-for="(rating, index) in computedRatings"

    class="rating-item border-bottom-1px"

    :key="index">

    {{format(rating.rateTime)}}

computed: {

ratings() {

return this.food.ratings

}

},

遍历整个列表,渲染出所有的ratings,包含时间,评价,用户,手指图标

(2)时间部分

通常日期的显示服务端不会显示时间,而是时间戳。而前端可以按照自己的要求改变为字符串。这里使用了moment的开源组件(Moment.js)可以添加format()方法,使用moment的方法即可

format(time) {

return moment(time).format('YYYY-MM-DD hh:mm')

}

至此完成了评价列表

(3)评价过滤功能

有两个维度实现过滤:首先可以查看评价类型(全部、推荐、吐槽)过滤评论的同时模块激活状态颜色改变;还有“只看有内容的评价”,将其设置为rating-select组件,在rating-select中的每个选项添加点击事件select,toggle,由于不能直接修改selectType,(传递过来的props)因此把这个props的值派发到父组件food,让后让父组件做修改,响应式更新数据再影响子组件。

因此在food组件中可以监听这两个方法onselect() ontoggle()控制改变。

三、food组件-rating-select组件

============================

1. 布局


主要是(全部、推荐、吐糟)+只看有内容的评论

<span @click="select(2)" class="block positive" :class="{'active': selectType===2}">{{desc.all}}

{{ratings.length}}

<span @click="select(0)" class="block positive" :class="{'active': selectType===0}">{{desc.positive}}

{{positives.length}}

<span @click="select(1)" class="block positive" :class="{'active': selectType===1}">{{desc.negative}}

{{negatives.length}}

只看有内容的评价

2. 实现


(1)rating-select组件接收数据

设置props,外部可以传入的变量。

接收ratings是个数组(通过ratings可以计算各部分的评价个数);selectType是选择类型(有三种类型,定义三种常量POSITIVE、NEGATIVE、ALL)使用常量增加可读性;onlycontent是否有内容;desc描述(对象默认描述:all:"全部" positive:“满意” negative:“不满意”)

const POSITIVE = 0 最后

最后写上我自己一直喜欢的一句名言:世界上只有一种真正的英雄主义就是在认清生活真相之后仍然热爱它

开源分享:docs.qq.com/doc/DSmRnRG…