综合案例 商场
调整目录
vant2
全部导入
① 安装 vant-ui
yarn add vant@latest-v2
② main.js 中注册
import Vant from 'vant'import 'vant/lib/index.css'
// 把vant中所有的组件都导入了
Vue.use(Vant)
③ 使用测试
<van-button type="primary">主要按钮</van-button>
<van-button type="info">信息按钮</van-button>
按需导入
① 安装 vant-ui (已安装)
yarn add vant@latest-v2
② 安装插件
npm i babel-plugin-import -D
③ babel.config.js 中配置
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
['import', {
libraryName: 'vant',
libraryDirectory: 'es',
style: true
}, 'vant']
]
}
④ main.js 按需导入注册
import Vue from 'vue';
import { Button } from 'vant';
Vue.use(Button);
⑤ 测试使用
<van-button type="primary">主要按钮</van-button>
<van-button type="info">信息按钮</van-button>
⑥ 提取到 vant-ui.js 中,main.js 导入
import '@/utils/vant-ui'
的作用是执行代码,不是导入变量故不用导出
// 导入按需导入的配置文件
import '@/utils/vant-ui'
目中的 vw 适配
目标:基于 postcss 插件 实现项目 vw 适配
官方配置
① 安装插件
yarn add postcss-px-to-viewport@1.1.1 -D1
② 根目录新建 postcss.config.js 文件,填入配置
// postcss.config.js
module.exports = {
plugins: {
'postcss-px-to-viewport': {
// 标准屏宽度
viewportWidth: 375
}
}
}
封装axios
import axios from 'axios'
// 创建axios实例,对创建axios实例进行自定义配置
// 好处:不会污染原始的axios实例
const instance = axios.create({
baseURL: 'http://smart-shop.itheima.net/index.php?s=/api';,
timeout: 5000
})// 自定义配置 请求/响应拦截器
// 添加请求拦截器
instance.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error)
})// 添加响应拦截器
instance.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么(默认axios会多一层data,需要响应拦截器处理一下)
return response.data
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error)
})
// 导出配置好的实例
export default instance----测试使用-----
组件内使用
import request from '@/utils/requset'
export default {
name: 'LoginPage',
async created () {
const res = await request({
url: 'http://smart-shop.itheima.net/index.php?s=/api/captcha/image';
})
console.log(res)
}
}
图形验证码功能
对响应结果解构赋值封装
{ "status": 200, "message": "success", "data": { "base64": "data:image/png;base64,xxx", "key": "$2y$10$rfeeAQ4CD0p4QgBk8kJyx.Xwn4u1UjIvogE/3pZVtv2.1tKMapiH2", "md5": "f25ae60901ff709150605330b8fb50d1" } }
api接口模块-封装图片验证码接口
toast轻提示
每个文件都需要显式导入自己要用的变量/函数/组件
注册安装:
import { Toast } from 'vant'
Vue.use(Toast)
两种使用方式
① 导入调用 (组件内 或 非组件中均可)(相当于导入了两次 因为Toast 是函数调用形式,不是组件标签)
import { Toast } from 'vant'
Toast('提示内容')
② 通过this直接调用 (必须组件内)
本质:将方法,注册挂载到了Vue原型上 vuex持久化处理 未登录用户无法进入一些核心页面(拦截) 访问权限页面时,拦截或放行的关键点? → 用户是否有登录权证 token 搜索历史基本渲染 点击搜索 (添加历史) 点击 搜索按钮 或 底下历史记录,都能进行搜索 ① 若之前 没有 相同搜索关键字,则直接追加到最前面 ② 若之前 已有 相同搜索关键字,将该原有关键字移除,再追加 清空历史:添加清空图标,可以清空历史记录 持久化:搜索历史需要持久化,刷新历史不丢失 静态结构,左中右三部分 数字框的数字,应该是外部传递进来的 (父传子) 点击 + - 号,可以修改数字 (子传父) 使用 v-model 实现封装 (:value 和 @input 的简写) 数字不能减到小于 1 可以直接输入内容,输入完成判断是否合法 :value="item.isChecked" :value="item.goods_num" 不能使用v-model 点击小选修改状态 小选控制全选 全选控制小选 编辑切换状态Vue.prototype.$toast = xxx</span></code></p><pre class="ne-codeblock language-jsx" style="border: 1px solid rgb(232, 232, 232); border-radius: 2px; background-color: rgb(249, 249, 249); padding: 16px; font-size: 13px; color: rgb(89, 89, 89);">this.$toast('提示内容')
短信验证倒计时
基础功能
验证码请求检验处理
封装短信验证请求接口
登录接口
响应拦截器
// 添加响应拦截器 统一处理错误
instance.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么(默认axios会多一层data,需要响应拦截器处理一下)
const res = response.data
// console.log(res)
if (res.status !== 200) {
// 提示
Toast(res.message)
// 抛出promise
return Promise.reject(res.message)
}
return response.datatoken存入vuex
storage存储模块
loading效果 节流-友好提示
全局前置导航守卫
封装接口,动态渲染
历史记录管理
搜索列表
搜索关键字搜索
分类id搜索
商品详细页
加入购物车
弹层显示
封装数字框组件
判断token登录状态
购物车
vuex获取存储数据
mapState渲染数据
getter动态统计
全选反选
数字框修改数量
删除功能
空购物车的处理
<div class="cart-box" v-if="isLogin && cartList.length > 0">
<!-- 购物车开头 -->
<div class="cart-title">
...
</div>
<!-- 购物车列表 -->
<div class="cart-list">
...
</div>
<div class="footer-fixed">
...
</div>
</div>
<div class="empty-cart" v-else>
<img src="@/assets/empty.png" alt="">
<div class="tips">
您的购物车是空的, 快去逛逛吧
</div>
<div class="btn" @click="$router.push('/')">去逛逛</div>
</div>
订单结算台
收货地址
订单结算
订单结算,有两种情况:
购物车结算,需要两个参数① mode="cart"② cartIds="cartId, cartId"
立即购买结算,需要三个参数① mode="buyNow"② goodsId="商品id" ③ goodsSkuId="商品skuId"
都需要跳转时将参数传递过来
购物车结算
购物车界面去支付传递mode和cartIds
商品界面传参 支付界面compute接收
加一个登录校验利用到mixins 将登录验证封装
import loginConfirm from '@/mixins/loginConfirm'export default {
name: 'ProDetail',
mixins: [loginConfirm],
...
}
坑!!!!!!!!!!!!!!!
🔥 根本问题:loginConfirm 是一个对象方法,但未被正确合并到组件实例中。
你的混入是这样写的:js
export default {
loginConfirm() {
// ...
}
}
但 Vue 的 mixins 要求你把方法写在 methods 属性里,否则不会自动绑定到组件实例上。✅ 正确写法应该是:
// src/mixins/loginConfirm.js
export default {
methods: {
loginConfirm() {
if (!this.$store.getters.token) {
this.$dialog.confirm({
title: '温馨提示',
message: '此操作需要先登录',
confirmButtonText: '去登录',
cancelButtonText: '再逛逛'
}).then(() => {
this.$router.replace({
path: '/login',
query: { backUrl: this.$route.fullPath }
})
}).catch(() => {})
return true
}
return false
}
}
}
💡 Vue 在合并 mixins 时会将 methods、data、created 等属性与组件自身配置合并。
如果你直接在混入对象顶层写函数,是不会被合并进 this 上下文的。
提交订单并支付
订单管理和个人中心
给name属性也是为了个人中心页面可以跳转
<!-- 在标签指定 name 属性的情况下,v-model 的值为当前标签的 name -->
<van-tabs v-model="active" sticky>
<van-tab name="all" title="全部"></van-tab>
<van-tab name="payment" title="待支付"></van-tab>
<van-tab name="delivery" title="待发货"></van-tab>
<van-tab name="received" title="待收货"></van-tab>
<van-tab name="comment" title="待评价"></van-tab>
</van-tabs>
退出登录
打包配置优化
配置publicPath
module.exports = {
// 设置获取.js,.css文件时,是以相对地址为基准的。
// https://cli.vuejs.org/zh/config/#publicpath
publicPath: './'
}
路由懒加载 & 异步组件, 不会一上来就将所有的组件都加载,而是访问到对应的路由了,才加载解析这个路由对应的所有组件
官网链接:https://router.vuejs.org/zh/guide/advanced/lazy-loading.html#%E4%BD%BF%E7%94%A8-webpack
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
const Search = () => import('@/views/search')
const SearchList = () => import('@/views/search/list')
const ProDetail = () => import('@/views/prodetail')
const Login = () => import('@/views/login')
const Pay = () => import('@/views/pay')
const MyOrder = () => import('@/views/myorder')
<br/>
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!