我的基于Vue的饿了么项目有感
我的基于vue的饿了么项目学习前端也有五个月了,学完所有知识点之后买了个基于vue的饿了么项目来做,在花费了几天的时间之后总算完成了,心有感慨之余打算写一篇博客来记录下我在这整个过程的收获创建基本项目结构整个项目的开始的第一步就是创建这个项目,用到的指令是vue init webpack project(project是你要创建的项目名称),在这里我便出现了问题, download tem...
我的基于vue的饿了么项目
学习前端也有五个月了,学完所有知识点之后买了个基于vue的饿了么项目来做,在花费了几天的时间之后总算完成了,心有感慨之余打算写一篇博客来记录下我在这整个过程的收获
创建基本项目结构
整个项目的开始的第一步就是创建这个项目,用到的指令是vue init webpack project(project是你要创建的项目名称),在这里我便出现了问题, download template 一直转不停,无法显示下一步,于是乎查询了一下这个问题,最后发现是我的hosts文件出了问题,原因是因为无法访问到Github导致东西一直下载不下来,需要在Hosts文件中重定向github的ip到自己的主机,如此便可继续下一步了。之后则是创建目录的名称以及其他一些东西,这里按个人所需进行取舍。创建项目完毕之后进入该项目的根目录,若有特殊需求可以根据自己个人所需进行配置的更改,若没有的则直接npm run dev 就可以看到vue的欢迎页面了,如图下
开始项目
这之后就可以开始着手这个饿了么项目了,先把原本的页面内容删掉,该项目一共有四个大块的组件分别是头部组件,商品组件,商家组件以及评论组件大致如下
在确定好大致的组件结构之后就可以开始对每个组件按照具体要求着手。
header 组件
header 组件整体上没有太大难度,总结来讲有以下几点
1、灵活运用flex伸缩盒子,我后面用flex的频率也很高,因为确实好用
2、在设置背景阴影的时候需要给这个阴影元素添加z-index,让他的层级比header低否则会挡住header
3、在商家详情里设置评分的时候,个人做法是用一个div元素包裹两个含有五角星文字的元素,然后让两个元素定位到相应的位置并且后面的五角星覆盖住前面的五角星,最后设置颜色以及给后面的五角星一个计算属性设置宽度,即可。代码如下
<div class="star">
<div class="star1">★★★★★</div>
<div class="star2" :style="{width:sellerscore}">★★★★★</div>
</div>
==========================
computed: {
sellerscore () {
let score = this.seller.score * 20 + '%'
return score
}
}
4、这里每一条优惠信息前的图标,在数据中给每个图标设置了对应的数字,从0-n,这里我们需要定义一个如下的数组,并且根据图标对应的数据给li设置class样式,然后根据样式来自动获取图标,代码如下,这里的seller.supports[i].type 即对应的数字。并且这里用到了scss中的自定义函数来减少代码的冗杂。
created() {
this.classMap = ['decrease', 'discount', 'special', 'invoice', 'guarantee']
},
================================
<span class="icon" :class="classMap[seller.supports[i].type]"></span>
================================
&.decrease {
@include bg-image("decrease_2");
}
&.discount {
@include bg-image("discount_2");
}
&.guarantee {
@include bg-image("guarantee_2");
}
&.invoice {
@include bg-image("invoice_2");
}
&.special {
@include bg-image("special_2");
}
之后头部组件效果如下
至此头部组件完成
商品组件
商品组件算是整个过程中比较有难点的一块了,注意点如下。
1、首先整个商品组件分为左边的菜单页,右边的商品页,以及最下方的购物车,这里购物车我们使用单独的组件
2、菜单页的写法没有难点,对应的图标和上面使用数组给li添加样式然后设置图标的方式一样,右边的商品页也没有太大难度,根据标注图设置对应样式即可,需要注意的是每个图标下面的那一段空白要用padding 而不是 margin 原因是空白下还有一个底部边框,用margin达不到这个效果。做好后效果如下
此处先忽略那个蓝色的加号,那个是之后要单独做的组件。
3、这里就要开始进入商品组件的重点部分了
3.1 首先是点击左边的菜单,菜单高亮,右边的商品页也要跳到对应的地方,并且右边的商品页可以滚动,且滚动到对应的菜单时左边菜单页高亮。
3.1.1 做法是,首先设置一个listHeight空数组,用来存放商品列表的所有的li的高度,注意是每个li叠加后得到的高度,而不是单独的每个li的高度,如下
calHeight () {
let height = 0
this.listHeight.push(height)
let foodsList = document.querySelectorAll('.foods-list')
for (var i = 0; i < foodsList.length; i++) {
var item = foodsList[i]
height += item.clientHeight
this.listHeight.push(height)
}
},
这里的.foods-list 就是每一个li 的class 样式,即遍历每个li 并且把每个li的高度叠加放到listHieght数组中,
3.1.2 之后给右边的商品列表整个设置better-scroll 让其可以滚动,需要注意的是 better-scroll 的使用,必须给父元素添加better-scroll ,并且子元素的高度必须比父元素高,如此才能让列表滚动起来,之后给右边的商品列表设置滚动事件,每次滚动获取scrollY 的值 代码如下
this.foodsScroll.on('scroll', (pos) => {
this.scrollY = Math.abs(Math.round(pos.y))
})
由于这里的y本身为负值且带有小数点所以需要用Math.abs 和 Math.round 来让其变成正整数。
3.1.3 商品页滚动菜单页高亮,点击菜单页跳转对应商品页 :这里只需要设置一个计算属性,利用上面获取的scrollY 和 listHeight , 遍历listHeight 数组,进行判断,最后返回当前的索引值,代码如下
currentIndex() {
for (var i = 0; i < this.listHeight.length; i++) {
var height1 = this.listHeight[i]
var height2 = this.listHeight[i + 1]
if (!height2 || (this.scrollY >= height1 && this.scrollY < height2)) {
return i
}
}
return 0
},
将这个计算属性赋给菜单页的每个li并且进行判断,当currentIndex === i 时为当前 li 添加current 样式,然后为其设置高亮即可达到商品页滚动菜单页高亮的效果。
点击菜单页,商品页跳转到对应的地方则比较简单,为li添加一个方法,并且传入当前遍历的i 和 事件函数对象 e ,之后调用对应的API即可,如下
<li v-for="(item, i) in goods" :key="item.name" class="item-wrap" :class="{'current':currentIndex===i}" @click="selectMenu(i,$event)">
=======================
selectMenu (i, e) {
if (!e._constructed) {
return
}
let foodsList = document.querySelectorAll('.foods-list')
let el = foodsList[i]
this.foodsScroll.scrollToElement(el, 300)
}
3.2 接下来开始做cartcontrol 即每个商品旁边的蓝色加号和+1之后左边出现减号的组件
3.2.1 这里需要给数据添加一个属性count ,写完样式后给加号的元素添加方法,如果count 不存在则让count 为 1,否则count ++ ,以此来得到每个商品的个数。减号同理,代码如下。
if (!this.food.count) {
Vue.set(this.food, 'count', 1)
} else {
this.food.count++
}
3.3 将所有被选择的商品渲染到的购物车组件中。
3.3.1 这时候在整个商品组件中遍历数据,将数据中存在count 属性的对象放到一个数组中传给购物车组件,这样就可以拿到所有的被选择的商品的对象数组,需要注意的是这里的selectedFoods 是计算属性,因为每次点击,都需要重新计算才能拿到最新的数据
selectedFoods () {
let foods = []
this.goods.forEach((good) => {
good.foods.forEach((food) => {
if (food.count) {
foods.push(food)
}
})
})
return foods
}
3.3.2 购物车组件拿到数据后就可以对其进行遍历渲染,之后就按照需求进行css、js的书写,并且为点击购物车出现的那个列表页设置better-scroll,使其可以滚动,另外还有阴影也这些就看个人需求。至此整个商品组件就完成了,这也是本次饿了么项目最难的部分。
评论组件和商家组件
剩下这两个组件就没有太大难度了,需要用的套路基本上都是前面使用过的没有太大难度,拿到数据进行遍历渲染,根据标注书写样式,根据需求书写代码,唯一需要注意的是商家组件中有一个模块需要设置better-scroll 并且是横向滚动,此时只需要在配置项中加上scrollX: true 即可,如果不想在横向滚动的过程中触发纵向滚动(整个商家组件需要添加滚动),则加上eventPassthrough: ‘vertical’ 即可。至此整个基于vue的饿了么项目就算是圆满成功了。
附上我的项目地址,http://sell.wazaxa.club,(手机端查看,并且该项目未使用自适应布局,故在375*667 即iphone6/7/8 的尺寸下浏览效果最佳)项目还有一些bug之后找时间补上。从开始打包这个项目到真正实现网上浏览这之间还有很多坑。。。之后找时间另写一篇博客。
第一次发博客,不足之处望指出。
更多推荐
所有评论(0)