Vue2项目

综合案例 商场

调整目录

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 -D

1

② 根目录新建 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原型上 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.data

token存入vuex

storage存储模块

vuex持久化处理

loading效果 节流-友好提示

全局前置导航守卫

未登录用户无法进入一些核心页面(拦截)

访问权限页面时,拦截或放行的关键点? → 用户是否有登录权证 token

封装接口,动态渲染

历史记录管理

  1. 搜索历史基本渲染

  2. 点击搜索 (添加历史)

点击 搜索按钮 或 底下历史记录,都能进行搜索

① 若之前 没有 相同搜索关键字,则直接追加到最前面

② 若之前 已有 相同搜索关键字,将该原有关键字移除,再追加

  1. 清空历史:添加清空图标,可以清空历史记录

  2. 持久化:搜索历史需要持久化,刷新历史不丢失

搜索列表

搜索关键字搜索

分类id搜索

商品详细页

加入购物车

弹层显示

封装数字框组件

  1. 静态结构,左中右三部分

  2. 数字框的数字,应该是外部传递进来的 (父传子)

  3. 点击 + - 号,可以修改数字 (子传父)

  4. 使用 v-model 实现封装 (:value 和 @input 的简写)

  5. 数字不能减到小于 1

  6. 可以直接输入内容,输入完成判断是否合法

判断token登录状态

购物车

vuex获取存储数据

mapState渲染数据

:value="item.isChecked"

:value="item.goods_num" 不能使用v-model

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>

订单结算台

收货地址

订单结算

订单结算,有两种情况:

  1. 购物车结算,需要两个参数① mode="cart"② cartIds="cartId, cartId"

  2. 立即购买结算,需要三个参数① 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/>

已有 4 条评论

  1. 新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com

  2. 新盘新项目,不再等待,现在就是最佳上车机会!

  3. 2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
    新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
    新车首发,新的一年,只带想赚米的人coinsrore.com
    新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
    做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
    新车上路,只带前10个人coinsrore.com
    新盘首开 新盘首开 征召客户!!!coinsrore.com
    新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
    新车即将上线 真正的项目,期待你的参与coinsrore.com
    新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
    新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com

  4. 华纳圣淘沙公司开户新手教程

    零基础学会(183-8890-9465薇-STS5099)
    华纳圣淘沙公司开户

    华纳圣淘沙公司开户保姆级教程(183-8890-9465薇-STS5099)

    一步步教你开通华纳圣淘沙公司账户(183-8890-9465薇-STS5099)

    华纳圣淘沙公司开户分步图解

    首次开户必看:(183-8890-9465薇-STS5099)
    华纳圣淘沙全攻略

    华纳圣淘沙公司开户实操手册(183-8890-9465薇-STS5099)
    华纳圣淘沙开户流程视频教程

    手把手教学:(183-8890-9465薇-STS5099)
    华纳圣淘沙公司开户

    华纳圣淘沙公司开户完全指南(183-8890-9465薇-STS5099)

发表评论:

陕ICP备2023000669号-1