2024年项目总结:vue(2),web开发难点

总结

技术学到手后,就要开始准备面试了,找工作的时候一定要好好准备简历,毕竟简历是找工作的敲门砖,还有就是要多做面试题,复习巩固。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

const component = this.$refs.component[current]

component.fetch && component.fetch()

},

}

二、购物车shop-cart组件

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

1. 概括

购物车shop-cart组件有多种状态:(1)没有购买商品时,购物车全部灰色(2)当购买商品时,购物车右上角回有商品件数,并且会按照商品计算出价格,(3)当达到配送金额会显示“去结算”,不然就显示“还差XX元起送”。其中对于购物车的设计主要使用了flex布局主要维护选择的商品。 Seller会在goods中声明成计算属性。Goods组件会接收一些tab组件传入的props,而tab的数据也是从app.vue中传入的。因此当动态获取seller之后props的获取是一个响应式的,可以一层层通过tab达到goods组件。

2. 布局

          

分为左块(logo+price+des)和右块(pay),右边的部分宽度固定,左侧自适应的flex布局。左侧有一个购物车logo,显示总金额,配送费部分 右侧结算。

购物车有多种状态:(1)没有购买商品时,购物车全部灰色(2)当购买商品时,购物车右上角回有商品件数,并且会按照商品计算出价格,(3)当达到配送金额会显示“去结算”,不然就显示“还差XX元起送”。

另外当购物车不为空时点击购物车会弹出浮层,显示购买的商品,也可以清空购物车,或者在里面添加或者删除商品。

¥{{totalPrice}}
另需配送费¥{{deliveryPrice}}元
{{payDesc}}

3. 实现

(1)页面样式

其中logo相对于父元素有超出的部分,因此需要设置宽度和定位。使用relative,并设置top: -10px。  box-sizing: border-box,圆角设置border-radius:50%

(2)组件引入

在goods组件中引入,并做一些绑定。

<shop-cart

ref=“shopCart”

:select-foods=“selectFoods”

:delivery-Price=“seller.deliveryPrice”

:min-price=“seller.minPrice”>

Seller会在goods中声明成计算属性。Goods组件会接收一些tab组件传入的props,而tab的数据也是从app.vue中传入的。因此当动态获取seller之后props是一个响应式的,可以一层层通过tab达到goods组件。

computed: {

seller() {

return this.data.seller

},

购物者主要要维护选择的商品。通过props传入。SelectFoods表示已选择的商品,是通过用户选择动态获取的,还有配送费delivery Price和最小起送费minPrice,这两个是直接可以从后台数据拿到。

props: {

selectFoods: {

type: Array,

default() {

return []

}

},

deliveryPrice: {

type: Number,

default: 0

},

minPrice: {

type: Number,

default: 0

},

}

(3)计算属性

1) totalPrice是商品总和,遍历所选择的商品,拿到商品的价格和数量计算而得。

2)TotalCount是计算商品的总数量,便于显示在购物车部分。

totalPrice() {

let total = 0

this.selectFoods.forEach((food) => {

total += food.price * food.count

})

return total

},

totalCount() {

let count = 0

this.selectFoods.forEach((food) => {

count += food.count

})

return count

},

3) payDesc是对于支付的描述:根据totalprice计算,有三种状态(当价格为空,显示“起送价”;当商品总价小与最小起送价,显示“还差XX起送”;其他,显示“去结算”)

4)PayClass当右边的按钮到达结算状态会被点亮,因而控制class的样式显示。

payDesc() {

if (this.totalPrice === 0) {

return ¥${this.minPrice}元起送

} else if (this.totalPrice < this.minPrice) {

const diff = this.minPrice - this.totalPrice

return 还差¥${diff}元起送

} else {

return ‘去结算’

}

},

payClass() {

if (!this.totalCount || this.totalPrice < this.minPrice) {

return ‘not-enough’

} else {

return ‘enough’

}

}

三、购物车cart-control组件

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

1. 概括


shop-control组件主要分为三个部分(减号 数字 加号),其中点击加号会触发两个动画:(1)cart-control组件的渐出,(2)购物车小球下落动画。

对于(1):首先,使用v-show控制组件只有商品件数大于零显示。每个按钮维护一个food,并且对于按钮点击绑定add()和decease()事件用于记录商品的数量count。同时在父组件goods中维护计算属性selectFood(),用于计算商品数量,父组件将selectfood作为props传入shop-cart,从而实现两个兄弟组件之间的数据交互。对于过渡动画,使用组件通过v-show驱动。外层偏移内层rotate滚动,从而实现一边偏移一边滚动的渐出效果显示。

2. 布局


主要分为三个部分(减号 数字 加号)减号部分有一个过渡动画

{{food.count}}

3. 实现


v-show控制显示,当商品大于零才会显示。

(1)添点击事件

对于每个按钮都会接收和维护一个food,当点击添加时触发add(),修改count值(对于vue来说count是我们自己定义的变量,不是data.json的,因此使用要用this.$set()赋值,而不能直接使用this.food.count++)同理decrease()做减法

props: {

food: {

type: Object

}

},

methods: {

add(event) {

if (!this.food.count) {

this.$set(this.food, ‘count’, 1)

} else {

this.food.count++

}

this.$emit(EVENT_ADD, event.target)

},

decrease() {

if (this.food.count) {

this.food.count–

}

}

}

(2)组件传值和使用

同时goods中需要维护一个计算属性selectFood(),遍历goods对于每一个good下面的food,判断商品数量,从而可以拿到已选商品数组。并将selectfood并且作为props传入shop-cart。(详细可以查看上面购物车组件代码)

selectFoods() {

const ret = []

this.goods.forEach((good) => {

good.foods.forEach((food) => {

if (food.count) {

ret.push(food)

}

})

})

return ret

},

(3)过渡动画的实现

一期:有两个方位的滚动,基础组件要有一个内层组件,外层组件负责平移,内层组件负责滚动。所有的动画都会基于vue的transition过渡动画。添加transition=move

使用transform:translate3D(0,0,0)(3D可以开启硬件加速使得动画更加流畅)transition 0.4s 线性缓动

对于inner的transform:rotate(0)

二期:使用组件name=’’move’通过v-show驱动。对于外层会有一个偏移操作,内层是一个span会有一个rotate滚动效果,从而实现一边偏移一边滚动的渐出效果显示

.cart-decrease

display: inline-block

padding: 6px

opacity: 1

.inner

display: inline-block

line-height: 24px

font-size: $fontsize-large-x

color: $color-blue

transition: all 0.4s linear

transform: rotate(0)

&.move-enter-active, &.move-leave-active

transition: all 0.4s linear

&.move-enter, &.move-leave-active

opacity: 0

transform: rotate(180deg)

四、购物车小球飞入动画

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

1. 概括


点击shop-control组件的加号会触发两个动画:(1)cart-control组件的渐出,(2)购物车小球下落动画。

对于(2):设计思路:想象购物车里面有很多隐藏的小球,点击按钮,小球会变到当前点击位置并显示,然后经过一个动画飞入购物车,并且支持多个小球同时在动画。首先定义balls数组用于存放所有小球,属性show默认设置为false。并在shop-cart中定义小球容器,v-show遍历小球,拿到true的小球做动画。并监听几个vue的钩子函数before-enter ,enter ,after-enter来做动画。在beforedrop中拿到点击的位置,并将购物车中的小球显示在该位置。在dropping中触发重绘reflow,并让做动画回到原来位置,从而实现小球下落,动画之后监听transtionend事件,触发afterDrop,修改小球show显示状态为false,回收小球,并将小球元素display设置为null。从而实现了一次小球下落。

2. 实现


问题(1)小球是根据按钮的位置处飞入,落点是购物车(2)连续点击小球动画是不会断的,可以有多个小球在页面上显示。

思路:想象小球都放在购物车里,里面有很多隐藏的小球,点击某一个按钮时,小球会变到当前点击位置,并显示,然后经过一个动画飞入购物车。并且支持多个小球同时存在。

(1)获取按钮位置

首先,点击cart-control触发事件,需要知道按钮的DOM元素。 定义一个事件EVENT_ADD=add,触发一个事件,派发到DOM元素,通过event.target可以拿到按钮。

add(event) {

if (!this.food.count) {

this.$set(this.food, ‘count’, 1)

} else {

this.food.count++

}

this.$emit(EVENT_ADD, event.target)

},

(2)添加动画触发函数

之后可以在外层goods组件中的监听到事件@onAdd,从而驱动购物车做小球飞入。

<cart-control @add=“onAdd” :food=“food”>

并且修改goods组件中的onAdd(),在函数中驱动drop()方法

onAdd(target) {

this.$refs.shopCart.drop(target)

},

(3)购物车组件中添加drop方法

在购物车shop-cart中定义一个方法drop() ,接收el也就是DOM元素,(按钮的位置)。

drop(el) {

for (let i = 0; i < this.balls.length; i++) {

const ball = this.balls[i]

if (!ball.show) {

ball.show = true

ball.el = el

this.dropBalls.push(ball)

return

}

}

},

在goods组件中,拿到shop-cart的引用,添加ref=”shopCart”,并且修改goods组件中的onAdd(),在函数中驱动drop()方法。

<shop-cart

ref=“shopCart”

:select-foods=“selectFoods”

:delivery-Price=“seller.deliveryPrice”

:min-price=“seller.minPrice”>

因此就完成了点击按钮,驱动shop-cart组件的下落动画。

(4)实现drop()方法 - 添加小球

1)首先,需要购物车中放入一些隐藏的小球。因此,在shop-cart组件中的data中添加一些ball,数组中是对象小球以及状态。

const BALL_LEN = 10

const innerClsHook = ‘inner-hook’

data() {

return {

balls: createBalls(),

listFold: this.fold

}

},

2)定义一个辅助函数CreateBalls,向数组中Push放入小球对象,小球的属性show的默认值为false,并返回数组。

function createBalls() {

const ret = []

for (let i = 0; i < BALL_LEN; i++) {

ret.push({

show: false

})

}

return ret

}

(5)实现drop()方法 - 添加小球容器

在shop-cart组件中定义小球容器ball-container,使用fixed布局,内部

遍历ball。

使用transition驱动过渡动画(外层下落ball,内层平移inner)。使用v-show遍历小球,默认小球全都是隐藏的。监听几个vue的钩子函数before-enter enter after-enter。

<transition

@before-enter=“beforeDrop”

@enter=“dropping”

@after-enter=“afterDrop”>

(6)实现drop()方法

1)当调用drop时(shop-cart组件中的方法),会驱动小球的transition过渡。因此需要遍历小球数组,找到第一个隐藏的小球,显示状态修改为true,并且保存按钮DOM到ball。

drop(el) {

for (let i = 0; i < this.balls.length; i++) {

const ball = this.balls[i]

if (!ball.show) {

ball.show = true

ball.el = el

this.dropBalls.push(ball)

return

}

}

},

2)此时,还需要一个下落的小球数组dropBalls。因此,在钩子函数created中定义数组dropballs保存正在下落的小球,把隐藏的小球放到下落小球里面。(不放在data中的原因:不需要响应式的)

created() {

最后

为了帮助大家更好的了解前端,特别整理了《前端工程师面试手册》电子稿文件。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

(6)实现drop()方法

1)当调用drop时(shop-cart组件中的方法),会驱动小球的transition过渡。因此需要遍历小球数组,找到第一个隐藏的小球,显示状态修改为true,并且保存按钮DOM到ball。

drop(el) {

for (let i = 0; i < this.balls.length; i++) {

const ball = this.balls[i]

if (!ball.show) {

ball.show = true

ball.el = el

this.dropBalls.push(ball)

return

}

}

},

2)此时,还需要一个下落的小球数组dropBalls。因此,在钩子函数created中定义数组dropballs保存正在下落的小球,把隐藏的小球放到下落小球里面。(不放在data中的原因:不需要响应式的)

created() {

最后

为了帮助大家更好的了解前端,特别整理了《前端工程师面试手册》电子稿文件。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 26
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值