Vue 学习记录(八)--- 智慧商城项目

322 阅读9分钟

theme: channing-cyan

Vue 核心技术与实战

智慧商城项目

项目收获

  • 完整电商购物的业务流程
  • 组件库 vant(按需导入)
  • 移动端 vw 适配
  • request 请求方法封装
  • storage 存储模块封装
  • api 请求模块封装
  • 请求响应拦截器
  • 嵌套路由配置
  • 路由导航守卫
  • 路由跳转传参
  • vuex 分模块管理数据
  • 项目打包 & 优化

创建项目

  • 安装脚手架
  • 创建项目
  • 选择自定义
  • 074451362b82990669f5f419915c130c.png

调整初始化项目目录

  • 将目录调整为符合企业规范的项目目录
  • 41c10908942678803935319e39ceeff1.png
  • 步骤
    1. 删除多余的文件
    2. 修改路由配置和 App.vue
    3. 新增两个目录 api / utils
      1. api 接口模块:发送 ajax 请求的接口模块
      2. utils 工具模块:自己封装的一些工具方法模块

vant 组件库

  • 第三方组件库 vant-ui
  • 组件库:第三方封装好了很多的组件,整合到一起就是一个组件库
  • 官网:vant-ui.github.io/vant-weapp/…
  • vant2 版本支持 vue2、vant3 & vant4 版本支持 vue3
  • 其它组件库
    • PC端:element-ui(饿了么)、ant-design-vue(阿里巴巴)
    • 移动端:vant-ui、Mint UI(饿了么)、Cube UI(滴滴)

vant 按需导入

  • 步骤:
    1. 查阅官方文档
    2. 安装 vant-ui
      • yarn add vant@latest-v2
    3. 安装插件
      • npm i babel-plugin-import -D
    4. bable.config.js 中配置
      • da4bbff4d672a3e4b798c95e091d8018.png
    5. main.js 按需导入注册
      • 5fd94eace779ef264d478ff001ecd414.png
    6. 测试使用
      • 5e0b651bd6ccfc674ed45871b6312121.png
      • c2dce8a4375f28855c1fae00dfc197d9.png

项目中的 vw 适配

  • 基于 postcss 插件,实现项目 vw 适配
  • postcss 会自动将 px 转换为 vw
  • 步骤:
    1. 安装插件
      • yarn add postcss-px-to-viewport@1.1.1 -D
    2. 根目录新建 postcss.config.js 文件,填入配置
      • bec4e3e429480282bd3621668fa31393.png

路由设计配置

  • 分析项目页面,设计路由,设置一级路由
  • 只要是单个页面并且独立展示的,都是一级路由
  • 73a952a173b31feaf46a43081c4980fb.png

使用 vant 组件,实现底部导航

  • 31aea119a727b23302a8367bb9288be6.png
  • 步骤
    1. vant-ui.js 按需引入
      • 在 vant 导航组件中找到 tabbar 复制粘贴到 vant-ui.js 中即可
      • d2b51b7be3fc303dc2c5f1f5e2f3a59c.png
    2. layout.vue 粘贴官方代码
      • 7914172c9bde8dbc9890b20cd701390f.png
    3. 修改文字、图标、颜色
      • 可根据自己的需求修改标签和图标
      • 在组件库中找到想要的图标样式,将名称赋值给 icon 属性即可
      • b5731655177a4c5f2e06c2716db3bb8b.png

配置二级路由

  • 基于底部导航,配置二级路由
  • 步骤:
    1. 配置二级路由(children 属性配置子路由)
    • ece521c455a618c0619aaf5408ad38b4.png
    1. 配置导航链接
      • vant 标签栏支持路由模式
      • ffe3e8438d3d5896723c28f247a43363.png
      • c20355d898035312b152397e6c9bafd1.png
    2. 配置路由出口
      • 07610287e4ea259fffb40fafbe1ccf10.png
    3. 当访问 '/' 时重定向到 '/home'
      • aa03b6a95009246ec4b19bd20ab0542f.png

登录页静态布局

  1. 准备工作
    • 新建 styles/common.less 重置默认样式
    • main.js 中导入 common.less
    • 图片素材拷贝到 assets 目录
  2. 登录页静态布局编写
    • 头部组件(vant)(NavBar)
    • 通用样式覆盖
    • 其他静态结构编写
  • 效果:
  • 58df11c94901847d8f2005e892d5b885.png

request 模块 - axios 封装

  • 将 axios 请求方法封装到 request 模块
  • 一般会对 axios 进行一些配置(配置基础地址,请求响应拦截器等)
  • 所以项目开发中,都会对 axios 进行基本的二次封装,单独封装到一个 request 模块中,便于使用维护
  • 步骤:
  1. 安装 axios
  2. 新建 request 模块 utils/request.js
  3. 创建实例和配置 并 导出
  4. 测试使用

图形验证码功能

  • 基于请求回来的 base64 图片,实现图形验证码功能
  • 说明:
    1. 图形验证码,本质就是一个请求回来的图片
    2. 用户输入图形验证码,用于强制人机交互,可以抵御机器自动化攻击
  • 需求:
    1. 动态将请求回来的 base64 图片,解析渲染出来
    2. 点击验证码图片盒子,要刷新验证码
  • 1b6adc7a9524a2619928530b9ecca3f6.png
  • 681159cb55ebff626270e4c6d784f0ce.png

api 接口模块 - 封装图片验证码接口

  • 之前模式的弊端:
    1. 页面中充斥着请求的代码,可阅读性不高
    2. 相同的请求没有复用
    3. 请求没有统一管理
  • 将请求封装为方法,统一存放到 api 模块,与页面实现分离
    • ae6be0af42368b8ec7b2b2f4cd3886b4.png
  • 封装为 api 模块的好处
    1. 请求与页面逻辑分离
    2. 相同的请求可以直接复用
    3. 请求进行了统一管理
  • 步骤
    1. 新建请求模块
      • 在 api/login.js
    2. 封装请求函数
      • 20a49d2bf6442ff3985b3f425154de06.png
    3. 页面中导入调用
      • caf39e3304234b949bd034fa48851cd9.png

Toast 轻提示

  • 参考 vant 官方文档
  • vant 组件库中的 Toast 轻提示
  • 步骤
    1. 注册安装
    • a13041ad3ef1e6f8e5a86c0dd809e1b4.png
    1. 使用方式
    2. 导入调用(任意地方)
    • 2ec40f26eee5716f39074b56712a18b9.png
    • 通过 this 调用 (组件内)
    • 本质:将方法注册挂载到了 Vue 原型上 Vue.prototype.$toast = xxx
    • this.$toast('提示内容')
    • 553791e72d4b45043b915a006fd79cd6.png

短信验证倒计时 - 点击按钮,实现倒计时效果

  • 步骤
    1. 准备 data 数据
    • 90c4ef87b26b7e3aea14ccc3b3a4d9b4.png
    1. 给按钮注册点击事件、并且切换显示文字
    • 1afb327e7cecdd72f9c12956f074df9b.png
    1. 开启倒计时
    • a2661534f68f3934ba8f69ec55ef5834.png
    1. 离开页面时清除倒计时
    • e200280302655a1292f58497764ec549.png

短信验证倒计时 - 倒计时之前的校验处理(手机号、验证码)

  • 步骤
    1. 设置变量并使用 v-model 绑定变量
    • 6e012f10f19f038ef880352a28206b55.png
    • eadb354d807cf81c4d1da54f573b391f.png
    1. methods 中封装校验方法(正则表达式)
    • 5271a2d67f2b32b636abe73442f22fc6.png
    1. 在发送手机验证码前进行校验
    • 5cd0f58036faf55054a3ba89134ec800.png

短信验证倒计时 - 封装短信验证接口,发送请求添加提示

  • 步骤
    1. 封装接口:
    • b8f939b1ae81deea8af5c12d0cab0fb4.png
    • f93220410d075371121de99aed285769.png
    1. 调用接口
    • f33cb1fbb7742ff025b216a65a89785d.png

登录功能

  • 封装 api 登录接口,实现登录
  1. 阅读接口文档,封装登录接口
  • 7f54ab889ead1ce86d6dd269299b6e92.png
  1. 登录前的校验(手机号、图形验证码、短信验证码)
  2. 调用接口并发送请求
  • 6a3fb35f16cc1b0e1c95a3f63a650874.png

响应拦截器统一处理错误提示

  • 响应拦截器是我们拿到数据的第一个数据流转站,可以在里面统一处理错误
  • a53a95734d096276226bdc4c8cd44a92.png
  • 配置拦截器
  • 6e4f66e8f1ee15a13d463d3a245fb21e.png

登录权证信息存储

  • vuex 构建 user 模块存储登录权证(token $ userId)
  • 步骤
    1. 构建 user 模块
    • c25997c3a1f0ace879e61bd662bd811d.png
    1. 挂载到 vuex
    • 39dc637b4155ff03850ca7ae71927245.png
    1. 提供 mutations
    • 631abc75b1f0c17286015bac02cec457.png
    1. 页面中 commit 调用
    • 34ff4c19634411f8622ef959ee8d8980.png

storage 存储模块 - vuex 持久化处理

  • 封装 storage 存储模块,利用本地存储,进行 vuex 持久化处理
  • 存在的问题
    1. vuex 中的数据在页面刷新后丢失
    2. 每次存取操作太长太麻烦
    • da59e6242d6afeb6c75e33ed1bba35da.png
  • 封装为 storage 模块后
    • b7e25f3901b2ecec7cf2bc7348143c88.png
    • 6d5b061dde2c460f5a7b84016bfd970a.png
  • 步骤:
    1. 封装 storage 方法
    • 2d00af76ad9dfa40d534a87d6fc8f8b9.png
    1. 在 vuex 的 user 子模块中调用方法
    • 8800a1fc51d59ceda252a355062b5e36.png
    1. 查看效果
    • 608669ea4c6d5ab20c0af1c4fcf48be8.png

添加请求 loading 效果

  • 在每次请求后台时,添加 loading 效果
  • 一次请求的结果可能需要一段时间后才能回来,此时给用户添加 loading 提示
  • 36d162ebeeadc7e0125f081112aa6cc7.png
  • 添加 loading 提示的好处
    1. 节流处理:防止用户在一次请求还没回之前,多次点击,发送无效请求
    2. 提升用户体验
  • 步骤:
    1. 请求拦截器中,每次请求时打开 loading
    • aa025d86fa88cee1cf0e6a43102c8cf1.png
    1. 响应拦截器中,每次响应时打开 loading
    • 19cad5ac594213023a26935a3fca35d4.png

页面访问拦截

  • 说明:本项目大部分页面游客都可以直接访问,如遇到需要登录才能进行的操作,提示并跳转到登录
  • 对于支付页、订单页等,必须是登录的用户才能访问,游客不能进入该页面,需要拦截未登录的用户
  • 路由导肮守卫 - 全局前置守卫
  • 官网:v3.router.vuejs.org/zh/guide/ad…
    1. 所有的路由一旦被匹配到都会先经过全局前置守卫
    2. 只有全局前置守卫放行,才会真正解析渲染组件,才能看到页面内容
    • 94b45751a53912c0e5a6b94cf20a7293.png
    • f5c04e9eb5469aa04162f8135711c972.png
  • 如果不配置 next 函数,则会拦截所有页面
  • 访问权限页面时,拦截和放行的关键点是看 -> 用户是否有登录权证 token
  • 832a0c5be3d9b4e985272514a8f40a12.png
  • 473ca77301d5febd955d777289e85047.png

首页 - 静态结构准备 & 动态渲染

  • 实现首页动态结构,封装接口,完成首页动态渲染
  • 步骤:
    1. 静态结构
      • vant组件
      • 7b5e3448f61cf81b8f8f39f60211422f.png
      • 9ae5b989f61ee503bde477c69f20d956.png
    2. 封装接口
      • 在 api/home.js 中封装请求接口
      • 9089c7049e3e662802a53ad497155319.png
    3. 页面调用
      • 在 created 中发送请求并在控制台输出,根据输出结果解构数据
      • 31073d43d82aacfc67a5cf15e18ae68f.png
      • 887f9da42a42ab4592f1ac4c086ef351.png
      • 在 data 中准备数据
      • 0a8661377fdd99ef26b378a34c73debc.png
    4. 动态渲染
      • 轮播图动态渲染
      • 365249a7e228bbd9e3f6619ce36375c0.png
      • 导航动态渲染
      • 62e070c10a3f183430e0c3b6f36caf08.png
      • 商品动态渲染
      • 由于商品界面使用了子组件单独封装 GoodsItem
      • 因此商品的动态渲染需要用到 父传子
      • 65020e9349475d60a942306bd4a2c985.png
      • 12d14ae24b2a15b6a1d529087dc6fe61.png
      • 5e7a8f70e9a29da92a09134a854e1aa8.png

搜索 - 历史记录管理

  • 构建搜索页静态布局,完成历史记录的管理
  • 需求
    1. 搜索历史的基本渲染
    2. 搜索历史的添加(追加)
      • 点击搜索按钮或最近搜索的条目,都能进行搜索
      • 若之前没有相同搜索关键字,则直接追加到最前面
      • 若之前已存在相同搜索关键字,将原来的关键字移除,再追加
      • f28b9764c04b2cc2f5ca463ed46bd38c.png
      • 3119f01d7a461fea5e82c0c2cb0d1fd8.png
      • 3e7982063ab5ab6464b79babd5f8bf86.png
    3. 清空历史:添加清空图标,可以清空历史记录
      • 22a2ce2818a489dbc6284967e74b3c72.png
      • f2978ef532e6442c94f330bbfc174cd3.png
    4. 持久化:搜索历史需要持久化存储,刷新后确保不丢失
      • f87655e387f696fd704457f5c9bc41e8.png
      • dc1902129ebf7c98270319c16a6a50b0.png
      • 7cc5e74fd9fdd1af5c0017a19df13ede.png
      • e1365e43dd18462e7fcb0e8bf506ada5.png

搜索列表 - 静态布局 & 渲染

  • 实现搜索列表页静态结构,封装接口,完成搜索列表页的渲染
  • 步骤
    1. 编写静态结构
      • 效果
      • dc404d2d83e8f126b23fc2ef37b8fe34.png
    2. 封装接口
      • 08501f6f5237e0ddfb5337ec6238354f.png
    3. 获取参数,调用接口
      • 8653c25500fd37ec29575510296df534.png
    4. 动态渲染
      • d128077ebb1bfcd9ab6b38858253e993.png

商品详情页 - 静态布局 && 渲染

  • 实现商品详情静态结构,封装接口,完成商品详情的渲染
  • 步骤
    1. 静态结构
      • 2418647963ebfdf6439983ea3638adc5.png
    2. 封装接口
      • 1121b7b6e01ca08d3cba14f5dd6631e6.png
    3. 动态路由获取参数
      • 629d8d27bf998ea7aae1c8b80f8c46c3.png
    4. 获取参数动态渲染
      • 调用api接口
      • 5d9c2421edba667852d76a844dd633db.png

加入购物车 - 唤起弹层

  • 目标:点击加入购物车时,唤起弹层效果
  • a5e5dc15fffb3106aee7663e37bb68c6.png
  • 步骤
    1. 从 vant 中找到 actionSheet 组件
      • af6849ab0e74a082189f74c66b829830.png
    2. 完善弹层结构和样式布局
      • 490bf1f1c291eef4bee5fc83d9060a3f.png
      • dd8a3e7ebb0d57e99e6bb3c64825c8f3.png
    3. 根据返回的数据,动态渲染有关的信息
      • 967736090847cb162f22e7c21247b56d.png

加入购物车 - 数字框组件的封装

  • 分析:组件名 CountBox
  • 7c3da0fbe227aaa1a9df0c5157a84d94.png
  1. 静态结构,左中右三部分
    • ea4a33f4627dade30513111c7fef2bcc.png
    • 2bd4a3f88774aa54a380258b07ce5e72.png
  2. 数字框的数字,由外部传递进来(父传子)
    • 712878f70dc71fae91e035833b7d0a40.png
  3. 点击 + - 号,可以修改数字(子传父)
    • d12bf8249cddb60682c7cdc3cfd00a9e.png
  4. 使用 v-model 实现封装(:value 和 @input 的简写)
  5. 数字不能减到小于1

加入购物车 - 判断 token 添加登录提示

  • 040507950e2cb970be9c5822303f5d64.png
  • 思路
    • token 存在:继续加入购物车操作
    • token 不存在:提示用户未登录,引导到登录页,登录后跳回上一页
  • 步骤
    1. 在 vant 组件库中找到 Dialog 组件,并了解相应的使用规则
      • 5e1b6ba48a2abb0aa336064014ca1993.png
    2. 给按钮绑定单击事件,并完善组件的文案
      • 053d26e62d35ee0febea6f4e0f479ba6.png
    3. 登录后回到商品详情页而不是首页,要加 backUrl
      • 8ab60a168f77bfbe29e584ee34c86076.png
    4. 完善登录逻辑代码
      • 7ed972311c84ab814026098f1d73c5a6.png

加入购物车 - 封装接口并发送请求

  • fdab150975907161b9455f623b1aac3d.png
  • 步骤
    • 在 api/cart.js 中封装接口
      • 84b827ddeb7d136c8c5cb693550ed875.png
    • 页面中调用接口
      • 68af4a14a52786bcd42d20ec499496da.png
    • 在请求头中添加 token,利用请求拦截器,只要存在 token,就将其添加到请求头中
      • 99486730c214fffdc352b8a879dfc848.png

购物车模块

  • 说明
    • 购物车数据联动关系较多,且通常封装为一些小组件
    • 为了方便维护,一般都会将购物车的数据基于 vuex 进行分模块管理
  • 需求分析
    • 基本静态结构
    • 构建 vuex cart模块,获取数据存储
    • 基于数据 动态渲染购物车列表
    • 封装 getters 实现动态统计
    • 全选、反选功能
    • 数字框修改数量功能
    • 编辑切换状态,删除功能
    • 空购物车处理

购物车模块 - 构建 vuex cart模块,获取数据存储

  • 步骤
    • 构建 modules/cart.js, 并在 store 中注册
      • 831f7f065801f9a051cf06d610705add.png
    • 封装 api 接口
      • 8b1f06c1bdb533afe39b67df950a8183.png
    • 封装 actions(异步) 和 mutations(修改state)
    • 在页面中使用 this.$store.dispatch 调用 dispatch
      • 98c8e22458dcd53e156dc267700c186b.png

购物车模块 - 基于数据动态渲染购物车列表

  • 使用辅助函数 mapState 将 cartList 直接映射到组件的计算属性中
  • 7f3df7ea9e08d18c15ebd436e853d989.png
  • 然后依据数据结构进行渲染
  • 6e65b3dcfb5292fe7b0feb9f0a388f73.png

购物车模块 - 封装 getters 模块进行动态统计

  • 封装 getters
    • 99417ac9fb6589f15f636302da2b4e06.png
  • 在 getters 中也可以获取 getters
    • 162b2fc1651fe1e9d4713f23db1ccf7a.png
  • 使用 mapGetters 进行映射
    • b2a435ba3686772eb3b8ec4454e889fe.png
  • 在页面中进行渲染
    • ccee1dca7ee464e37752eb127499cd40.png
    • 9e7fd954ae2c5e3caaed16415756ca01.png

购物车模块 - 全选与反选

  • 创建全选 getters

  • 01caf28a72fff2d5eeaf171e924dbad1.png

  • 给单项商品绑定单击事件,并在全选 getters 中判断是否所有的单项商品都选中

  • 点击全选时将所有单项商品的选择框重置

  • 79a76f851d9aaf3e9880b13a87326d71.png

购物车模块 - 数字框修改数量

  • 点击数字框的加减号,对购物车中的商品数量进行加减
  • 23f175895ad8ce7e11be949cc271993c.png
  • 封装 api 接口
  • fe697d9fccead48e4d1f5068158cf9d4.png
  • 注册点击事件并向 vuex 中的 action 传参
  • 3e3c5ee59d819e19a24668f0a91e648a.png
  • 在 action 中调用api接口
  • 6fc9890bdd5b0d7fe733c8cd15bf3d98.png
  • 小妙招,如何在注册点击事件时传递多个参数
  • 4daa20ce83930f1734b9a557cbcc0acc.png

购物车模块 - 编辑切换状态

  • 点击右上角的编辑后,右下角的结算变成删除,并且 isAllCheck = false
  • 设置 isEdit 变量,并绑定单击事件,点击编辑时将 isEdit 取反
    • 3f6473198831e6c3f6e49784fb9c8d24.png
  • b1d10ced9270f2b4fafdc16ea7fbeb9c.png
  • 使用 watch 监听,当 isEdit 为 true 时,调用 store 中的 mutation,改变全选状态
    • 94ccc7236817fd02d051a36e1ef78403.png

购物车模块 - 删除商品

  • 封装 api 接口
    • 5a090fb2b6fff324e5e046a1fbe094c0.png
  • 给删除按钮绑定单击事件,点击时调用 actions 中的方法
    • 8f5d739faa59bd9801aa913f23c537f7.png
    • e9f0015456b5ac882bfe50ac02cbe157.png
  • 删除成功后切换回结算
    • 74b2cf4917d15a7ea7bf9fa27bf87c84.png

购物车模块 - 空购物车页面

  • 当购物车为空或未登录时,展示
    • 4555e2ef58ae69542e7c0efb55967fba.png
  • 使用 v-if 和 v-else 控制两个盒子
    • 68686923da5e99ff24e57f0f7eb63fa7.png

订单结算台 - 页面布局与数据渲染

  • 563466d5e1de10c6a9e119cbf94315b4.png
  • 封装 api 接口(获取地址列表)
    • 0dd5ea365bd0fd08a2400c5730b2631d.png
  • 设置相关变量和计算属性等
    • 6ba48d9c19ba4b1c87acc70fcedb0619.png

订单结算台 - 购物车结算

  • 6bbd5272f85748311f3ba8e5c3e9e49c.png
  • 封装 api 接口
    • 6ab0e4652106d6d6b1ead457045e247a.png
  • 跳转传递查询参数 mode 和 cartIds
    • 2dd6c0e4ece400741257288f24c0478d.png
  • 页面中 $route.query 接收参数
    • 951d124cde2a91031b95c8b3c9117b6d.png
  • 调用接口获取数据
    • 6fd3ddaaa5965cf2340272abc2b7ea9c.png
  • 渲染数据

订单结算台 - 立即购买结算

  • 6bcaa4ccdf3ec1e65c8a68f817912a97.png
  • 点击跳转传参
    • fe328ae9bbaacc842663fb77ee237d42.png
  • 基于 mode 等参数发送请求进行渲染
  • mixins
    • 功能:需要将一个组件内的功能提取为公共部分,方便其它组件使用
    • 将登录提示弹出框提取到 mixins 的 longinConfirm 中
      • 8620e4beb6244c6258bb139ecdd7d359.png
    • 在组件中导入 mixins
      • 7a930e780a0dfb7b135a878d21f19e07.png

订单结算台 - 提交订单

  • 封装 api 接口
  • 在页面中绑定单击事件并调用接口
  • (参考项目文档)

订单管理页面 + 个人中心

  • 退出登录功能
  • 清除 vuex 中的 cart 和 user 模块信息 -(参考项目文档)

打包优化 - 打包指令及说明

  • 说明:vue 脚手架知识开发过程中,协助开发的工具 -- 脚手架不参与上线
  • 打包的作用
    1. 将多个文件压缩合并成一个文件
    2. 语法降级
    3. less sass ts 语法解析
    4. ...
  • 打包后可以生成浏览器能够直接运行的网页 =》 即需要上线的源码
  • vue 脚手架提供了打包命令,可以直接使用
  • yarn build / npm run build
  • 结果:会在项目的根目录自动创建文件夹 dist,dist中的文件就是打包后的文件,只需要放到服务器中即可
  • 配置:默认情况下,需要放到服务器根目录打开
  • 若希望在子目录中双击打开,需要在 vue.config.js 中添加 publicPath: './'

打包优化 - 路由懒加载

  • 目标:当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果完美把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应的组件,这样就更加高效了
  • 步骤
  1. 异步组件改造