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

已有 2 条评论

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

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

发表评论:

陕ICP备2023000669号-1