Vue2外卖总结
作者:互联网
Vue2外卖总结
先看一下效果,这是跟随硅谷外卖做的一个小项目。但是很多都是没有接口导致许多不太一致。
简介:
这是一个基础Vue2实现的一个外卖项目,部分图如上所示,数据没有调用一个接口,全都是模拟数据。相关视频在哔哩哔哩尚硅谷。链接https://www.bilibili.com/video/BV1hs411E7cB?spm_id_from=333.337.search-card.all.click 。组件部分:axios better-scroll core-js element-ui mockjs swipper vuex xue-router等
目录结构为:
src│App.vue│main.js│src.txt│├─api│ajax.js│index.js│├─common│└─stylus│mixins.styl│├─components│├─AlertTip││AlertTip.vue│││├─CartControl││CartControl.vue│││├─Food││Food.vue│││├─FoosterGuide││FoosterGuide.vue│││├─HeaderTop││HeaderTop.vue│││├─ShopCart││ShopCart.vue│││├─ShopHeader││ShopHeader.vue│││├─ShopList│││ShopList.vue│││││└─images││├─shop│││1.jpg│││2.jpg│││3.jpg│││4.jpg│││││└─stars││star24half@2x.png││star24off@2x.png││star24on@2x.png││star36half@2x.png││star36off@2x.png││star36on@2x.png││star48half@2x.png││star48off@2x.png││star48on@2x.png│││└─Star││star.vue│││└─stars│star24half@2x.png│star24off@2x.png│star24on@2x.png│star36half@2x.png│star36on@2x.png│star48half@2x.png│star48off@2x.png│star48on@2x.png│├─filters├─mock│mock.js│├─pages│├─Login│││Login.vue│││││└─images││captcha.svg│││├─Msite││Msite.vue│││├─Order│││Order.vue│││││└─images││└─order││person.png│││├─Profile││Profile.vue│││├─Search││Search.vue│││└─Shop││Shop.vue│││├─ShopGoods││ShopGoods.vue│││├─ShopInfo││ShopInfo.vue│││└─ShopRatings│ShopRating.vue│├─router│index.js│├─static└─storeactions.jsgetters.jsindex.jsmutations.jsstate.js
主要模块
1.登录注册(未注册自动注册)
2.个人中心
3.外卖首页
4.商家部分(商品列表,评价,等等)
功能实现
1.手机号验证,验证码验证,验证码设定时效
2.首页上方轮播图(非自动轮播)
3.购物车部分(查看,修改,遮盖)
4.评价筛选部分(过滤)
5.评价分数星计算
1.注册登录
登录部分两种不同的登录方式,短信登录与密码登录。使用正则对手机号格式验证,格式正确才能够发送验证码,否则发送验证码按钮为disable。验证码通过mock随机数生成,设置指定时间让其消失,实现验证码时效效果。当手机号或者验证码不正确弹出提示框。
2.首页
上方为轮播,需要滑动显示轮播效果。categorysArr页面为挂载时,使用mock获取的数据。通过设置watch监视,来判断categorysArr当中是否已经存在数据。this.$nextTick(), 作用就是等待页面渲染完毕后再去执行当中代码。因为需要计算高度。下方商家列表是v-for循环遍历mock数据,来渲染页面。
<nav class="msite_nav">
<div class="swiper">
<div class="swiper-wrapper">
<div
class="swiper-slide"
v-for="(categorys, index) in categorysArr"
:key="index"
>
<a
href="javascript:"
class="link_to_food"
v-for="(category, index) in categorys"
:key="index"
>
<div class="food_container">
<img :src='category.img_url' alt="">
</div>
<span>{{ category.name }}</span>
</a>
</div>
</div>
<!-- 如果需要分页器 -->
<!-- <div class="swiper-pagination"></div> -->
<!-- 如果需要滚动条 -->
<!-- <div class="swiper-scrollbar"></div> -->
</div>
</nav>
watch: {
categorys() {
if (this.categorysArr.length !== 0) {
this.$nextTick(() => {
new Swiper(".swiper", {
// loop 设置左右滑动模式 如果是true则会无限滑动
// loop: true, // 循环模式选项
// 如果需要分页器 pagination指的是分页器
// pagination: {
// el: ".swiper-pagination",
// },
// scrollbar: {
// el: ".swiper-scrollbar",
// },
// 如果需要前进后退按钮
// navigation: {
// nextEl: ".swiper-button-next",
// prevEl: ".swiper-button-prev",
// },
});
});
}
},
},
3.个人中心
首先就是判断用户使用哪种登录方式来显示登录页面的不同内容。以及首页右上角是显示登录还是已经登录。未登录不会显示立即退出按钮。未绑定手机号显示手机号为绑定。如果绑定则不显示。
4.商家
(1)商品列表
单击加号放入购物车,当购物车当中没有该商品数据则减号不显示。价格对应下方计算,三种显示模式,未选中商品,显示 ¥20起送;选中但是为满20元起送显示 还差¥XX元起送 ;>=20元,则显示为绿色结算。购物车部分对应显示商品列表,并且小圆点显示购物车当中数量。
左侧导航栏点击后,会跳转到对用商品列表,跳转过程商品列表滑动显示。需要先获取对用列表的top值,然后为每一个li添加点击事件,让top值修改为对应top值的高度。
对应购物车当中的数据也是存储在vuex当中,相关vuex的讲解我也有文章讲解,感兴趣的各位可以去查看我的vuex当中的解释。
methods: {
// 相关better-scroll都能够在官网查找到相关的api
// 初始化滑动
initScroll() {
this.scroll = new BScroll(".menu-wrapper",{
mouseWheel: true,
click: true
});
this.foodScroll = new BScroll(".foods-wrapper", {
probeType: 2, // 惯性滑动不会触发
mouseWheel: true,
// 可能会出现兼容性的问题,所以在此处最好还是加上
click: true,
});
// 绑定滚动监听
this.foodScroll.on("scroll", ({ x, y }) => {
// console.log(y);
this.scrollY = Math.abs(y); //返回绝对值
});
// 解决惯性滑动不刷新的bug
this.foodScroll.on("scrollEnd", ({ x, y }) => {
// console.log(y);
this.scrollY = Math.abs(y); //返回绝对值
});
this.scroll.refresh();
this.foodScroll.refresh();
},
// 初始获取top
initTops() {
let top = 0;
this.tops.push(top);
const lis = this.$refs.foodsUl.getElementsByClassName("food-list-hook");
Array.prototype.slice.call(lis).forEach((li) => {
top += li.clientHeight;
this.tops.push(top);
// console.log(this.tops);
});
},
// 获取索引 左侧点击切换 scroolTo(x, y, time, easing(缓动函数,一般不建议修改))
clickMenu(index) {
this.scrollY = -this.tops[index];
// scrollTo显而易见滚动到,后面300位时间
this.foodScroll.scrollTo(0, this.scrollY, 300);
},
// 点击显示Food,小图切换大图显示
showFood(food) {
this.food = food;
this.$refs.food.toggleShow();
},
},
// 挂载的时候调用上方方法,this.$nextTick等获取到数据后执行
mounted() {
this.$store.dispatch("get_restaurant", () => {
this.$nextTick(() => {
this.initScroll();
this.initTops();
});
});
},
这是相关html当中的内容
<div class="foods-wrapper">
<ul ref="foodsUl">
<li
class="food-list-hook"
v-for="(good, index) in goods"
:key="index"
>
<h1 class="title">{{ good.name }}</h1>
<ul>
<li
class="food-item bottom-border-1px"
v-for="(food, index) in good.foods"
:key="index"
>
<div class="icon">
<img
width="57"
height="57"
:src="food.image"
@click="showFood(food)"
/>
</div>
<div class="content">
<h2 class="name">{{ food.name }}</h2>
<p class="desc">{{ food.description }}</p>
<div class="extra">
<span class="count">月售{{ food.sellCount }}份11</span>
<span>好评率{{ food.rating }}%</span><br /><br />
<span class="now">¥{{ food.price }}</span>
<span class="old" v-if="food.oldPrice"
>¥{{ food.oldPrice }}</span
>
</div>
<div class="cartcontrol-wrapper"></div>
<CartControl :food="food" />
</div>
</li>
</ul>
</li>
</ul>
</div>
(2)评价
需要计算星星,该部分为一个通用组件,计算方法如下代码,读者自行查看结构挺简单的。
<template>
<!-- 接收参数 -->
<div class="star" :class="'star-' + size">
<span
class="star-item"
v-for="(sc, index) in starClasses"
:class="sc"
:key="index"
></span>
</div>
</template>
export default {
name: "Star",
// 组件调用需要传过来参数,评价分数,以及星星大小
props: {
// 传过来的分数
score: Number,
// 使用星星的大小
size: Number,
},
computed: {
starClasses() {
const score = this.score;
const scs = [];
// ons代表满星几颗
const ons = Math.floor(score);
for (let i = 0; i < ons; i++) {
scs.push("on");
}
// 首先半星只会出现 0 或 1 个由于小数部分计算会出现问题,所以采用*10计算
const halfs = (score * 10) % 10;
if (halfs > 5) {
scs.push("half");
}
// 总分为5颗星,其他的(满星,半星)添加进来后剩下的都是灰色星星
while (scs.length < 5) {
scs.push("off");
}
return scs;
},
},
};
下方评价现实就是一个过滤器,拿到mock模拟的评价数组,根据不同的点击事件,来显示不同的内容。
(3)商家信息
首先还是拿到由mock模拟的数据,然后渲染页面。值得一提的是,图片的左右滑动。
<section class="section">
<h3 class="section-title">商家实景</h3>
<div class="pic-wrapper">
<ul class="pic-list" ref="picsUl">
<li class="pic-item" v-for="(pic, index) in info.pics" :key="index">
<img width="120" height="90" :src="pic" />
</li>
</ul>
</div>
</section>
methods: {
initScroll() {
new BScroll(".shop-info", {
click: true,
});
// 首先拿到ref
const ul = this.$refs.picsUl;
// 每张图片大小 120px
const Width = 120;
// 间隔 6px
const space = 6;
// 用来动态计算数组长度,来设置宽度
const count = this.info.pics.length;
ul.style.width = (Width + space) * count - space + "px";
new BScroll(".pic-wrapper", {
click: true,
scrollX: true,
});
},
},
o", {
click: true,
});
// 首先拿到ref
const ul = this.$refs.picsUl;
// 每张图片大小 120px
const Width = 120;
// 间隔 6px
const space = 6;
// 用来动态计算数组长度,来设置宽度
const count = this.info.pics.length;
ul.style.width = (Width + space) * count - space + “px”;
new BScroll(".pic-wrapper", {
click: true,
scrollX: true,
});
},
},
标签:总结,vue,const,外卖,2x,jpg,js,Vue2,png 来源: https://blog.csdn.net/qq_53157160/article/details/123590666