VUE复习(购物平台项目)持续更新...

一.明确功能模块

二. 路由配置 - 一级路由

但凡是单个页面,独立展示的,都是一级路由

路由设计:

  • 登录页

  • 首页架子

    • 首页 - 二级

    • 分类页 - 二级

    • 购物车 - 二级

    • 我的 - 二级

  • 搜索页

  • 搜索列表页

  • 商品详情页

  • 结算支付页

  • 我的订单页

router/index.js 配置一级路由,新建对应的页面文件


import Vue from 'vue'
import VueRouter from 'vue-router'
import Layout from '@/views/layout'
import Search from '@/views/search'
import SearchList from '@/views/search/list'
import ProDetail from '@/views/prodetail'
import Login from '@/views/login'
import Pay from '@/views/pay'
import MyOrder from '@/views/myorder'
​
Vue.use(VueRouter)
​
const router = new VueRouter({
  routes: [
    {
      path: '/login',
      component: Login
    },
    {
      path: '/',
      component: Layout
    },
    {
      path: '/search',
      component: Search
    },
    {
      path: '/searchlist',
      component: SearchList
    },
    {
      path: '/prodetail/:id',
      component: ProDetail
    },
    {
      path: '/pay',
      component: Pay
    },
    {
      path: '/myorder',
      component: MyOrder
    }
  ]
})
​
export default router

三. 路由配置-tabbar标签页

https://vant-contrib.gitee.io/vant/v2/#/zh-CN/tabbar

vant-ui.js 引入组件


import { Tabbar, TabbarItem } from 'vant'
Vue.use(Tabbar)
Vue.use(TabbarItem)

layout.vue

  1. 复制官方代码

  2. 修改显示文本及显示的图标

  3. 配置高亮颜色


<template>
  <div>
    <!-- 二级路由出口 -->
    <van-tabbar active-color="#ee0a24" inactive-color="#000">
      <van-tabbar-item icon="wap-home-o">首页</van-tabbar-item>
      <van-tabbar-item icon="apps-o">分类页</van-tabbar-item>
      <van-tabbar-item icon="shopping-cart-o">购物车</van-tabbar-item>
      <van-tabbar-item icon="user-o">我的</van-tabbar-item>
    </van-tabbar>
  </div>
</template>

四. 路由配置 - 二级路由

  1. router/index.js配置二级路由


import Vue from 'vue'
import VueRouter from 'vue-router'
import Layout from '@/views/layout'
import Search from '@/views/search'
import SearchList from '@/views/search/list'
import ProDetail from '@/views/prodetail'
import Login from '@/views/login'
import Pay from '@/views/pay'
import MyOrder from '@/views/myorder'
​
import Home from '@/views/layout/home'
import Category from '@/views/layout/category'
import Cart from '@/views/layout/cart'
import User from '@/views/layout/user'
​
Vue.use(VueRouter)
​
const router = new VueRouter({
  routes: [
    {
      path: '/login',
      component: Login
    },
    {
      path: '/',
      component: Layout,
      redirect: '/home',
      children: [
        {
          path: 'home',
          component: Home
        },
        {
          path: 'category',
          component: Category
        },
        {
          path: 'cart',
          component: Cart
        },
        {
          path: 'user',
          component: User
        }
      ]
    },
    {
      path: '/search',
      component: Search
    },
    {
      path: '/searchlist',
      component: SearchList
    },
    {
      path: '/prodetail/:id',
      component: ProDetail
    },
    {
      path: '/pay',
      component: Pay
    },
    {
      path: '/myorder',
      component: MyOrder
    }
  ]
})
​
export default router
  1. 准备对应的组件文件

    • layout/home.vue

    • layout/category.vue

    • layout/cart.vue

    • layout/user.vue

  2. layout.vue 配置路由出口, 配置 tabbar


<template>
  <div>
    <router-view></router-view>
    <van-tabbar route active-color="#ee0a24" inactive-color="#000">
      <van-tabbar-item to="/home" icon="wap-home-o">首页</van-tabbar-item>
      <van-tabbar-item to="/category" icon="apps-o">分类页</van-tabbar-item>
      <van-tabbar-item to="/cart" icon="shopping-cart-o">购物车</van-tabbar-item>
      <van-tabbar-item to="/user" icon="user-o">我的</van-tabbar-item>
    </van-tabbar>
  </div>
</template>

五.登录页静态布局

使用组件

  • van-nav-bar

vant-ui.js 注册


import { NavBar } from 'vant'
Vue.use(NavBar)

Login.vue 使用


<template>
  <div class="login">
    <van-nav-bar title="会员登录" left-arrow @click-left="$router.go(-1)" />
    <div class="container">
      <div class="title">
        <h3>手机号登录</h3>
        <p>未注册的手机号登录后将自动注册</p>
      </div>
​
      <div class="form">
        <div class="form-item">
          <input class="inp" maxlength="11" placeholder="请输入手机号码" type="text">
        </div>
        <div class="form-item">
          <input class="inp" maxlength="5" placeholder="请输入图形验证码" type="text">
          <img src="@/assets/code.png" alt="">
        </div>
        <div class="form-item">
          <input class="inp" placeholder="请输入短信验证码" type="text">
          <button>获取验证码</button>
        </div>
      </div>
​
      <div class="login-btn">登录</div>
    </div>
  </div>
</template>
​
<script>
export default {
  name: 'LoginPage'
}
</script>
​
<style lang="less" scoped>
.container {
  padding: 49px 29px;
​
  .title {
    margin-bottom: 20px;
    h3 {
      font-size: 26px;
      font-weight: normal;
    }
    p {
      line-height: 40px;
      font-size: 14px;
      color: #b8b8b8;
    }
  }
​
  .form-item {
    border-bottom: 1px solid #f3f1f2;
    padding: 8px;
    margin-bottom: 14px;
    display: flex;
    align-items: center;
    .inp {
      display: block;
      border: none;
      outline: none;
      height: 32px;
      font-size: 14px;
      flex: 1;
    }
    img {
      width: 94px;
      height: 31px;
    }
    button {
      height: 31px;
      border: none;
      font-size: 13px;
      color: #cea26a;
      background-color: transparent;
      padding-right: 9px;
    }
  }
​
  .login-btn {
    width: 100%;
    height: 42px;
    margin-top: 39px;
    background: linear-gradient(90deg,#ecb53c,#ff9211);
    color: #fff;
    border-radius: 39px;
    box-shadow: 0 10px 20px 0 rgba(0,0,0,.1);
    letter-spacing: 2px;
    display: flex;
    justify-content: center;
    align-items: center;
  }
}
</style>

添加通用样式

styles/common.less 设置导航条,返回箭头颜色


// 设置导航条 返回箭头 颜色
.van-nav-bar {
  .van-icon-arrow-left {
    color: #333;
  }
}

六. request模块 - axios封装

接口文档:https://apifox.com/apidoc/shared-12ab6b18-adc2-444c-ad11-0e60f5693f66/doc-2221080

演示地址:http://cba.itlike.com/public/mweb/#/

基地址:http://cba.itlike.com/public/index.php?s=/api/

使用 axios 来请求后端接口, 一般都会对 axios 进行一些配置 (比如: 配置基础地址,请求响应拦截器等等)

一般项目开发中, 都会对 axios 进行基本的二次封装, 单独封装到一个模块中, 便于使用

目标:将 axios 请求方法,封装到 request 模块

  1. 安装 axios


npm i axios
  1. 新建 utils/request.js 封装 axios 模块

    利用 axios.create 创建一个自定义的 axios 来使用

    http://www.axios-js.com/zh-cn/docs/#axios-create-config


/* 封装axios用于发送请求 */
import axios from 'axios'
​
// 创建一个新的axios实例
const request = axios.create({
  baseURL: 'http://cba.itlike.com/public/index.php?s=/api/',
  timeout: 5000
})
​
// 添加请求拦截器
request.interceptors.request.use(function (config) {
  // 在发送请求之前做些什么
  return config
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error)
})
​
// 添加响应拦截器
request.interceptors.response.use(function (response) {
  // 对响应数据做点什么
  return response.data
}, function (error) {
  // 对响应错误做点什么
  return Promise.reject(error)
})
​
export default request
  1. 获取图形验证码,请求测试


import request from '@/utils/request'
export default {
  name: 'LoginPage',
  async created () {
    const res = await request.get('/captcha/image')
    console.log(res)
  }
}

七. 图形验证码功能

  1. 准备数据,获取图形验证码后存储图片路径,存储图片唯一标识


async created () {
  this.getPicCode()
},
data () {
  return {
    picUrl: '',
    picKey: ''
  }
},
methods: {
  // 获取图形验证码
  async getPicCode () {
    const { data: { base64, key } } = await request.get('/captcha/image')
    this.picUrl = base64
    this.picKey = key
  }
}
  1. 动态渲染图形验证码,并且点击时要重新刷新验证码


<img v-if="picUrl" :src="picUrl" @click="getPicCode">

16. toast 轻提示

https://vant-contrib.gitee.io/vant/v2/#/zh-CN/toast

两种使用方式

  1. 导入调用 ( 组件内非组件中均可 )


import { Toast } from 'vant';
Toast('提示内容');
  1. 通过this直接调用 ( 组件内 )

main.js 注册绑定到原型


import { Toast } from 'vant';
Vue.use(Toast)

this.$toast('提示内容')

八. 短信验证倒计时功能

(一) 倒计时基础效果

  1. 准备 data 数据


data () {
  return {
    totalSecond: 60, // 总秒数
    second: 60, // 倒计时的秒数
    timer: null // 定时器 id
  }
},
  1. 给按钮注册点击事件


<button @click="getCode">
  {{ second === totalSecond ? '获取验证码' : second + `秒后重新发送`}}
</button>
  1. 开启倒计时时


async getCode () {
  if (!this.timer && this.second === this.totalSecond) {
    // 开启倒计时
    this.timer = setInterval(() => {
      this.second--
​
      if (this.second < 1) {
        clearInterval(this.timer)
        this.timer = null
        this.second = this.totalSecond
      }
    }, 1000)
​
    // 发送请求,获取验证码
    this.$toast('发送成功,请注意查收')
  }
}
  1. 离开页面销毁定时器


destroyed () {
  clearInterval(this.timer)
}

(二) 验证码请求校验处理

  1. 输入框 v-model 绑定变量


data () {
  return {
    mobile: '', // 手机号
    picCode: '' // 图形验证码
  }
},
    
<input v-model="mobile" class="inp" maxlength="11" placeholder="请输入手机号码" type="text">
<input v-model="picCode" class="inp" maxlength="5" placeholder="请输入图形验证码" type="text">
  1. methods中封装校验方法


// 校验输入框内容
validFn () {
  if (!/^1[3-9]\d{9}$/.test(this.mobile)) {
    this.$toast('请输入正确的手机号')
    return false
  }
  if (!/^\w{4}$/.test(this.picCode)) {
    this.$toast('请输入正确的图形验证码')
    return false
  }
  return true
},
  1. 请求倒计时前进行校验


// 获取短信验证码
async getCode () {
  if (!this.validFn()) {
    return
  }
  ...
}

(三) 封装接口,请求获取验证码

  1. 封装接口 api/login.js


// 获取短信验证码
export const getMsgCode = (captchaCode, captchaKey, mobile) => {
  return request.post('/captcha/sendSmsCaptcha', {
    form: {
      captchaCode,
      captchaKey,
      mobile
    }
  })
}
  1. 调用接口,添加提示


// 获取短信验证码
async getCode () {
  if (!this.validFn()) {
    return
  }
​
  if (!this.timer && this.second === this.totalSecond) {
    // 发送请求,获取验证码
    await getMsgCode(this.picCode, this.picKey, this.mobile)
    this.$toast('发送成功,请注意查收')
    
    // 开启倒计时
    ...
  }
}

九. 封装api接口 - 登录功能

api/login.js 提供登录 Api 函数


// 验证码登录
export const codeLogin = (mobile, smsCode) => {
  return request.post('/passport/login', {
    form: {
      isParty: false,
      mobile,
      partyData: {},
      smsCode
    }
  })
}

login/index.vue 登录功能


<input class="inp" v-model="msgCode" maxlength="6" placeholder="请输入短信验证码" type="text">
<div class="login-btn" @click="login">登录</div>
​
data () {
  return {
    msgCode: '',
  }
},
methods: {
  async login () {
    if (!this.validFn()) {
      return
    }
    if (!/^\d{6}$/.test(this.msgCode)) {
      this.$toast('请输入正确的手机验证码')
      return
    }
    await codeLogin(this.mobile, this.msgCode)
    this.$router.push('/')
    this.$toast('登录成功')
  }
}


VUE复习(购物平台项目)持续更新...
http://localhost:8090//archives/vuefu-xi
作者
cchen
发布于
2024年08月18日
许可协议