项目地址: https://github.com/Chocolate1999/Vue-family-bucket-SSR-Koa2-full-stack-development-from-Meituan
学习地址:传送门
融汇 前端+服务端 全栈项目,提供后端数据接口,源码开放,可进行二次开发与优化。
Column 1 | Column 2 | Column 3 |
---|---|---|
登录/注册 | SMTP服务 | 城市服务 |
推荐服务 | 搜索服务 | 地图服务 |
购物车 | 订单设计 | 组件复用设计 |
接口设计 | 数据对象模型 | 思维&技巧 |
【Vue全家桶+SSR+Koa2全栈开发】(一)Vue基础
【Vue全家桶+SSR+Koa2全栈开发】(二)Vuex基础
【Vue全家桶+SSR+Koa2全栈开发】(三)Koa2基础
【Vue全家桶+SSR+Koa2全栈开发】(四)mongoose基础
【Vue全家桶+SSR+Koa2全栈开发】(五) Redis基础
【Vue全家桶+SSR+Koa2全栈开发】(六) Nuxt.js基础
【Vue全家桶+SSR+Koa2全栈开发】(七) 项目搭建与配置
【Vue全家桶+SSR+Koa2全栈开发】学习笔记整合 (全)
本项目提供开发时的源码,可以进行二次开发及优化,欢迎 contributor 参与!
① Star 本仓库,然后 Fork 到自己 github,下载代码到本地
# install dependencies
$ npm run install
② 配置后端数据库文件,启动 MongoDB 和 Redis 服务(详情请见上文笔记)
③ 二次开发运行
npm run dev
1、城市服务组件
浏览器在发出请求的时候,会有一个 request
,在服务器端可以拿到 requset.ip
,然后就可以取数据中心作映射,根据 ip
来定位城市,服务器拿到 city
后再下发给浏览器。
原本实现方式: 当页面渲染完了,向服务器发送请求,甚至可以发一个空内容,然后按照上述实现原理来获取 city
。即在 mounted 事件之后,向服务器发送请求,然后服务器下发城市名称。(页面发送请求渲染,然后又异步请求获取城市名,共两次请求)
缺点:网络请求浪费,影响用户体验,异步获取的城市会 “闪” 一下。
项目实现方式:当浏览器去请求文档的时候,服务端 ip已经知道了,那个时候就可以拿到对应的城市,立即返回数据给浏览器。做法就是通过 vuex
来同步状态,然后通过 SSR
异步请求就能得到数据。
2、用户数据&状态
浏览器发送一个 request
请求,根据 cookie
,服务器通过 passport
与 redis
来验证当前是否是登录状态,返回 username
。
3、产品详情页开发
本项目产品列表页(如下图所示)
产品详情页(如下图所示)
每一个列表对应着多个 item
,每个 item
与详情页是一对一关系,而上述两个页面路由是没有关联关系的。特此说明:本项目没有 产品库,因此路由没有根据 id
来,依旧是根据搜索关键词 keyword
。另外,产品列表页和产品详情页之间做了登录拦截。
接着,关于产品详情页是如何跳转到购物车的呢?
购物车页面如下图所示,可以看到,页面路由依旧是没有任何关联,但从下图地址栏可见,有一个重要的id
属性。因为产品详情页不能与购物车创建一对一映射关系,即在进入产品详情页时,购物车页面是不存在的。当点击购买跳转到购物车时才会创建一个购物车。另外,产品详情页和购物车之间做了登录拦截。
4、登录逻辑
/users/signin
self.$axios.post('/users/signin', {
username : window.encodeURIComponent(self.username),
password : CryptoJS.MD5(self.password).toString()
})
location.href="/"
5、退出逻辑
退出(exit.vue)组件,采用中间件来实现退出操作。
点击users/components/public/header/user.vue
文件中的退出后跳转到退出页(page/exit.vue)
之后,自动的去执行退出操作所以利用middleware
机制,触发这个获取退出的接口,让接口响应完之后,我们再做自动化的执行动作
6、搜索相关
每输入一个字母都进行一次请求,显然浪费性能,因此引入lodash
插件,使用debounce
,函数防抖。
import _ from 'lodash'
input:_.debounce(async function(){
let self=this;
let city=self.$store.state.geo.position.city.replace('市','')
self.searchList=[]
let {status,data:{top}}=await self.$axios.get('/search/top',{
params:{
input:self.search,
city
}
})
self.searchList=top.slice(0,10)
},300)
参考:由浅入深学习lodash的debounce函数
7、购物车相关
父组件pages/cart.vue
通过asyncData获取数据(接口:/cart/getCart
)
传给子组件 list.vue
所有订单数据,由子组件全部渲染出来,通过cartData
变量联系,如果我在子组件中更改了购买商品的数量,也就是cartData中的值被更改了,那么,我们在父组件监听的total(所有订单总价),也会重新计算
另外,购物车会创建一个订单,创建成功后才会跳转支付页面,但需考虑支付的是哪一个订单,于是支付和订单之间有一个依赖逻辑联系,但是支付和购物车之间是没有任何依赖的,虽然支付的动作是由购物车发起的,但是购物车和支付之间的桥梁是订单。
项目部分截图如下文所示:
笔记内容按照 中文文案排版指北 进行排版。
欢迎关注微信公众号:小狮子前端Vue
谢谢您的支持!✿✿ヽ(°▽°)ノ✿
注:本仓库不参与商业行为,也请各位读者周知。(This warehouse is not involved in commercial activities.)
转载使用请注明出处,谢谢!