背景:先学习前端基础(html、css、js、ajax、axios),学习vue2,学习vue3(响应式、计算属性、watch、生命周期hook、路由、pinia、组件通信........)
day1
先create vue,如图
然后导包,打开脚手架,确保能跑起来
项目起步
1、然后用git工具进行管理,在vscode的terminal中输入
git init
git add .
git commit -m "init"
2、然后就完成了项目初始化和git管理。
3、然后进行ElementPlus自动按需导入配置(上官网查看):
4、然后进行axios基础配置,搭建一个基础的架子
5、然后根据项目页面配置路由,创建一级路由:Layout和Login,二级路由:Home和Category...
6、然后进行静态资源引入和ErrorLen安装
7、然后在styles下新建var.scss,在config文件中自动导入,免去每次都要导入的麻烦
8、然后初始化阶段就完成了,开始做真正的项目
day2
Layout
1、Layout模块静态模板搭建
2、再然后引入阿里的字体图标库(font-class)
<link rel="stylesheet" href="//at.alicdn.com/t/font_2143783_iq6z4ey5vu.css">
font-class地址已经给大家生成好了,复制粘贴到index.html即可
3、下一步:使用后端接口渲染(render)一级导航
步骤:根据接口文档封装接口函数、发送请求获取数据列表、v-for渲染页面
4、下一步实现吸顶交互(向下滑动到一定值时,顶部导航在最上面不动)
步骤:准备导航组件基础结构、(用插件vueUse)获取滚动距离、用滚动距离做判断条件控制组件盒子展示隐藏
5、下一步:Pinia优化重复请求(两个导航列表是一致的,但是要发两次网络请求,浪费。使用Pinia集中式管理数据,再把数据给组件使用),如下图
home页面
1、搭建一下home的大致结构
2、实现home-整体结构拆分以及分类渲染
3、下一步呢:实现home-banner轮播图实现(直接使用elementplus插件实现,然后拿数据渲染就ok了)
4、然后进行面板组件封装(解决复用问题:新鲜好物和人气推荐模块结构相似、内容不同,通过组件封装可以实现服用结构的效果)(非复杂的模板抽象成props,复杂的结构模板抽象为插槽)
5、然后实现新鲜好物和人气推荐模块:准备模板(HomePanel组件)、定制Props、定制插槽内容(接口 + 渲染模板)
6、再写一个图片懒加载(vueUse),优化网页。(当图片进入视口时,发送图片资源请求)(可以把懒加载指令封装为插件,然后在入口文件只需要负责注册插件即可)
7、然后实现Product产品列表(常规的列表渲染):准备静态模板、封装接口、获取数据渲染模板、图片懒加载
8、再然后进行GoodsItem组件的封装(在项目中的每个业务模块中都需要用到同样的商品展示模块,没必要重复定义,封装起来,方便复用)
一级分类
1、然后简单配置一下路由
2、然后写一个面包屑导航(常规):准备组件模板、封装接口函数、调用接口获取数据(使用路由参数useRoute)、渲染模板
3、然后把首页的轮播图迁移到category(重写接口,其他复制即可)
4、再写一个分类列表渲染
!!!!!
路由缓存问题:由于用户从'/users/johny'到'/user/jolyne'时,相同的组件实例将被重复使用,生命周期hook将不会被调用,导致数据无法更新
5、然后解决一下本项目的路由缓存问题(方案一:让组件实例不复用,强行销毁重建;方案二:监听路由变化,变化之后执行数据更新操作)
建议用方案二,因为banner轮播图是可以复用的,如果用方案一,banner轮播图必须要再次发送请求,不够优雅
!!!!!
6、然后呢,用逻辑函数把同一组件中的独立的业务封装,提升代码的可维护性(思想),具体实现呢:category文件夹中含有banner轮播图和分类数据两个业务,我们需要把这两个业务分别封装
二级分类
1、然后给二级分类做一个面包屑导航
2、再然后做基础商品列表实现:实现基础列表渲染、添加额外参数实现筛功能、实现无限加载功能(太麻烦了,就不一步一步写了)
虽然已经过了第二天了,但只要没睡,就不算新的一天(^_^)
详情页
然后就开始做详情页了
1、先整体认识以及路由配置
2、然后做详情页的基础数据渲染(常规)
3、再做热榜区的基础数据渲染(常规)(封装Hot热榜组件、获取渲染基础数据、适配不同的标题Title、视频不同列表内容)
day3
4、然后对图片预览组件进行封装(实现通过小图切换大图显示的功能、放大镜效果)
5、通过小图切换大图功能:静态模板、为小图绑定事件,记录当前激活下标值、通过下标切换大图显示、通过下标实现激活状态显示
6、放大镜效果:引入vueuse的useMouseInElement,使用elementX, elementY, isOutside三个参数,
用watch监听这三个参数
下图是运算逻辑
根据运算逻辑算得left和top之后,给滑块,控制滑块跟随移动,放大之后的图(简称大图)是未放大图的两倍大,横向纵向都是left、top的 - 2 倍,然后给大图,控制大图移动即可
7、sku组件:商品规格(颜色、大小....)
使用别人写好的sku组件(太复杂了,太麻烦了,没必要自己写),完成 选择商品规格功能
8、然后把components文件夹中的imageView组件和sku组件写成插件,并在全局引用,这样就不需要再引入了
登录
1、先进行路由配置
2、然后做一下登录页面的表单校验(校验账号密码格式....)(elementPlus内置了表单校验功能,按照组件要求配置必要参数)
3、然后做一下条款协议的校验(由于内置的校验功能不能满足我们的需求,所以使用自定义校验)
4、然后再做一下整体校验(处理用户上来直接点击登录的情况)
5、然后实现一下基础的登录业务流程(表单校验通过 => 封装登录接口 => 调用登录接口 => 登录成功/失败的后续逻辑)
6、然后用pinia管理用户数据,以便于多个组件访问用户数据
7、然后做到使用户数据持久化,保持token在刷新时不丢失(存到localStorage)(pinia-plugin-persistedstate插件,适用于Pinia的持久化存储)
8、再然后做一下登录和非登录状态下的模板适配(同一区域在不同登录状态下的不同模板显示)
9、然后实现一下 在请求拦截器中携带token 的功能(token作为用户标识,在很多接口中必须携带token才可以正确获取资源,所以需要在接口调用时携带token)
config.headers.Authorization = `Bearer ${token}`
记得这段代码是按照后端的要求来的,是固定的
10、退出登录功能实现(点击退出登录弹出确认框、点击确认按钮实现退出登录逻辑、清除当前用户信息&&跳转到登录页面)
11、token失效401拦截处理(o_o)(token的有效性可以保持一定的时间,如果用户一段时间不做任何操作,token就会失效,使用失效的token再去请求一些接口,接口就会报401状态码错误,需要做额外处理(重新登录))
购物车:最难的功能
业务逻辑梳理{ 未登录 => 所有操作不走接口直接操作Pinia中的本地购物车列表
已登录 => 所有操作直接走接口,操作完毕获取购物车列表更新本地购物车列表 }
1、实现本地加入购物车的功能(用pinia实现添加购物车功能,再把数据持久化)
2、给头部购物车添加一个列表渲染功能
3、给头部购物车添加一个删除功能(
法一:找到要删除项的下标值,用slice 不好写,但是可能不用遍历全部
法二:用filter 好写,但是要遍历全部
)
4、实现头部购物车统计计算功能(计算属性)
5、实现列表购物车基础数据渲染
6、实现列表购物车单选功能
day4
7、实现列表购物车全选功能(底层实现v-model,不能直接用v-model,因为v-model的计算属性是只可读的)
8、做两个接口分别实现 加入 和 删除 购物车功能,(之前做的都是直接操作Pinia中的本地购物车列表(未登录状态),现在我们做的是已登录状态的操作)
9、退出登录,清空购物车数据(在cartStore中补充清除购物车的action、userStore中找到退出登录action,执行清除业务)
10、登录时,把本地购物车的数据和服务端购物车数据进行合并操作(登录时调用合并购物车接口,获取最新购物车列表,覆盖本地)
结算
1、先做路由配置和整体数据渲染
2、地址切换 - 打开弹框交互式实现
3、地址激活交互实现:点击哪个,哪个地址就变成激活状态,然后把地址覆盖
4、提交订单功能实现,提交订单跳转之后,更新购物车状态
支付
1、渲染基础数据
2、完成支付功能:跳转支付地址(get请求)(订单id+回跳地址url)
//支付地址
const baseURL = 'http://pcapi-xiaotuxian-front-devtest.itheima.net/'
const backURL = 'http://127.0.0.1:5173/paycallback'
const redirectUrl = encodeURIComponent(backURL)
const payUrl = `${baseURL}pay/aliPay?orderId=${route.query.id}&redirect=${redirectUrl}`
支付完毕后,跳转到回跳地址url(订单id+支付状态)
3、做支付成果展示功能
4、封装倒计时函数(格式化时用插件dayjs)(这一步代码比较集中,就粘过来了)
//封装倒计时逻辑函数
import { ref,computed, onUnmounted } from "vue"
import dayjs from "dayjs"
export const useCountDown = () => {
let timer = null
//1、响应式数据
const time = ref(0)
//格式化时间为 XX分XX秒
const formatTime = computed(() => {
return dayjs.unix(time.value).format('mm分ss秒')
})
//2、开启倒计时的函数
const start = (currentTime) => {
//开始倒计时的逻辑
//核心逻辑:每隔一秒减一
time.value = currentTime
timer = setInterval(() => {
time.value--
},1000)
}
//组件销毁时,清除定时器
onUnmounted(() => {
timer && clearInterval(timer)
})
return {
formatTime,
start
}
}
记得渲染。
会员中心--最后一个模块
1、路由配置:三级路由
2、个人中心信息渲染( 个人信息 部分直接使用Pinia中的数据, 猜你喜欢 部分走接口获取)
3、tab切换获取状态数据并渲染
4、分页逻辑实现
然后就ok了
终于写完了,这下可以好好玩黑神话悟空了
jjuaien/vue3-rabbit (github.com) <= 手写的源代码在这里