Vue智慧商城案例

智慧商城

知识点目录

实现

按照结构创建vue-cli脚手架,创建项目

初始化设置一下文件

(有部分修改和增加)

  1. 增加两个文件夹------api 和 utils
  2. 删除之前关于vue页面样式的一些文件
  3. 修改路由配置
js 复制代码
const router = new VueRouter({
  // 默认路由是一个空数组
  routes: []
})
  1. 修改app.vue,把之前的样式删掉,只留一个路由出口即可

认识第三方Vuet组件库vant-ui

组件库:

第三方封装好了很多很多的组件,整合到一起就是一个组件库

Vant 2 - 轻量、可靠的移动端组件库 (gitee.io)

vant全部导入和按需导入

全部:

按需:

按需导入这里需要在根目录再创建一个js文件:babel.config.js

js 复制代码
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
  plugins: [
    ['import', {
      libraryName: 'vant',
      libraryDirectory: 'es',
      style: true
    }, 'vant']
  ]
}
  • 但是之后我们用到的组件增多时,全部写在main.js里就不太合适了
  • 所以我们现在在utils文件夹里写一个新的vant-ui.js文件用来存放这些组件

项目中的vw适配

目标:基于postcss插件实现项目vw适配

在根目录(不是src)创建一个新的js文件:postcss.config.js

js 复制代码
module.exports = {
  plugins: {
    'postcss-px-to-viewport': {
      // vw适配的标准屏的宽度(iPhoneX)
      // 设计图 750 ,调成1倍 =》适配375标准屏幕
      // 设计图 640 ,调成1倍 =》适配320标准屏幕
      viewportWidth: 375
    }
  }
}

路由设计配置

  1. 先搞清楚一级路由和二级路由,并完成文件的准备

比如:

  1. 配路由规则(数组里面包对象)
js 复制代码
//router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '@/views/login'
import Layout from '@/views/layout'
import Search from '@/views/search'
import SearchList from '@/views/search/list'
import ProDetail from '@/views/prodetail'
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
  1. 路由设计配置
  • 目标1:阅读vant组件库文档,实现底部导航tabbar
  • 目标2:基于底部导航,完成二级路由配置
  1. 配相关的二级组件
  2. 配置二级路由:在相关的一级路由里嵌套,用children
js 复制代码
import Home from '@/views/layout/home'
import Category from '@/views/layout/category'
import Cart from '@/views/layout/cart'
import User from '@/views/layout/user'

 {
      path: '/',
      component: Layout,
      redirect: '/home',//重定向:一进页面,默认首页路由
      children: [
        { path: '/home', component: Home },
        { path: '/category', component: Category },
        { path: '/cart', component: Cart },
        { path: '/user', component: User }

      ]
    },
  1. 配置导航链接

配合route和to路径可以实现导航栏点击高亮转换

js 复制代码
<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>
  1. 配置路由出口,在app.vue
js 复制代码
<router-view></router-view>

登录静态布局

1. 准备工作

  1. 以后所有的 公共通用样式 都可以写在styles文件夹里
js 复制代码
//common.less
// 重置默认样式
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

// 文字溢出省略号
.text-ellipsis-2 {
  overflow: hidden;
  -webkit-line-clamp: 2;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-box-orient: vertical;
}

// 添加导航的通用样式
.van-nav-bar {
  .van-nav-bar__arrow {
    color: #333;
  }
}
  1. 在main.js里导入common.less
js 复制代码
import '@/styles/common.less'
  1. 图片素材拷贝到assets目录中

2. 登录页静态布局编写

  1. 头部组件 NavBar
    • 引入
    • 页面
  2. 左箭头通用样式
  3. 静态未渲染的页面结构编写

utils/vant-ui.js

js 复制代码
import Vue from 'vue'
import { NavBar } from 'vant'

Vue.use(NavBar)

views/login/index.js

js 复制代码
        <!-- 头部,用到了vant插件NavBar -->
        <!-- 返回上一页 @click-left="$router.go(-1)" -->
        <van-nav-bar
           title="会员登录"
           left-arrow
           @click-left="$router.go(-1)"
           />

在这里给头部导航的返回箭头加了一个通用样式

css 复制代码
  //添加导航的通用样式
  //不把这个样式在行内写,而写在通用样式里,是因为不仅这一个导航栏需要
  //写两层是为了增加它的权重
  .van-nav-bar{
    .van-nav-bar__arrow{
        color: #333;
    }
}

request模块-axios封装-发请求

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

  • 获取图像验证码
  • 获取短信验证码
  • 登录

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

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

创建request模块

  1. 安装axios: yarn add axios

  2. 新建request模块

utils/request.js

其中有部分修改,看注释

js 复制代码
import axios from 'axios'
// 创建axios实例,将来对创建出来的实例进行自定义配置
const instance = axios.create({
// 基地址记得修改成你自己的
  baseURL: 'http://cba.itlike.com/public/index.php?s=/api/',
  timeout: 5000
  // headers: { 'X-Custom-Header': 'foobar' }
})

// !!!!这里需要注意的是:
// 你直接从官网上拦截器处cv过来的是配置在最原始的axios上的
// 你需要把下面的axios换成比如你在这里创建的新的instance

// 自定义配置 - 请求/响应 拦截器
// 添加请求拦截器
instance.interceptors.request.use(function (config) {
  // 在发送请求之前做些什么
  return config
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error)
})

// 添加响应拦截器
instance.interceptors.response.use(function (response) {
  // 2xx 范围内的状态码都会触发该函数。
  // 对响应数据做点什么
  // return response
  //  (默认axios会多包装一层data,所以我们这里打点一下data)
  return response.data
}, function (error) {
  // 超出 2xx 范围的状态码都会触发该函数。
  // 对响应错误做点什么
  return Promise.reject(error)
})

// 导出配置好的实例
export default instance
  1. 创建实例&配置,导出实例

views/login/index.vue

js 复制代码
import request from '@/utils/request'
export default {
  name: 'LoginPage',
  async created () {
  //在智慧商城接口文档处找------获取图形验证码
    const res = await request.get('/captcha/image')
    console.log(res)
  }
}

图形验证码功能完成

目标:基于请求回来的base64图片,实现图形验证码功能

js 复制代码
export default {
  name: 'LoginPage',
  data () {
    return {
      picCode: '', // 请求用户输入的图形验证码
      picKey: '', // 将来请求传递的图形验证码的唯一标识
      picUrl: '' // 存储请求渲染的图片地址
    }
  },
  async created () {
    // 整个这个发请求的部分也可以封装成一个方法methods
    this.getPicCode()
    // const res = await request.get('/captcha/image')
    // console.log(res)
  },
  methods: {
    // 获取图形验证码
    async getPicCode () {
      // 基于返回的结果进行解析
      const { data: { base64, key } } = await request.get('/captcha/image')
      this.picUrl = base64 // 存储地址,设置给img src
      this.picKey = key // 存储唯一标识,将来验证需要携带
    }
  }
}
</script>

然后在页面:src="picUrl"渲染一下

js 复制代码
//这里还加了一个v-if表示有图片的时候才会渲染,避免了刷新出现显示图片损坏
//把标签自带的alt=""删掉,不然点击事件不生效
<img v-if="picUrl" :src="picUrl" @click="getPicCode">

这样就可以得到图形验证码了,并且每次刷新都会更换,每次点击也会更换

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

目标:将请求封装成方法,统一存放到api模块,与页面分离

以前的模式:

采用封装api模块的模式:

就举我们刚刚写的的这个请求图片验证码的请求,把红色框部分封装到api里的login.js里(这里面可以存放所有有关login界面的请求),然后这一部分就可以替换成调用了

api/login.js

js 复制代码
// 此处用于存放所有登录相关的接口请求
import request from '@/utils/request'

// 需要export导出(这里是按需导出,所以页面中也需要按需导入)
// 1. 获取图形验证码请求
export const getPicCode = () => {
  // 必须加return,如果不加的话,将来在login的vue里就接收不到你返回来的promise结果了
  return request.get('/captcha/image')
}

views/login/index.vue

js 复制代码
const { data: { base64, key } } = await getPicCode()

---------------------------------------------------效果跟刚才一样^^成功

Toast轻提示

  1. 组件库导入
js 复制代码
import Vue from 'vue'
import { Toast } from 'vant'

Vue.use(Toast)
  1. 调用
js 复制代码
import { Toast } from 'vant';
Toast('获取图形验证码成功')// 组件内/非组件都可以,必须写导入

this.$toast('获取图形验证码成功')//只能必须在组件内,但是可以不写上面导入那条

短信验证倒计时

  1. 点击按钮,实现倒计时效果

从变量出发,在data里写

js 复制代码
totalSecond: 60, // 总秒数
second: 60// 当前描述,开定时器,对second--
timer:null //定时器id
js 复制代码
 <button @click="getCode">
     {{ second === totalSecond ? '获取验证码' : second + '秒后重新发送'}}
  </button>
js 复制代码
// 在methods中写
 getCode () {
      // 当前目前没有定时器开着,且totalSecond和second一致(也就是秒数归位)才可以倒计时
      if (!this.timer && this.second === this.totalSecond) {
      // 开启倒计时
        this.timer = setInterval(() => {
          console.log('正在倒计时...')
          this.second--
          // 避免减到负数
          if (this.second <= 1) {
            clearInterval(this.timer)
            this.timer = null// 重置定时器
            this.second = this.totalSecond// 归位
          }
        }, 1000)
      }
    },
    // 这个是为了当你离开这个页面后把定时器停掉,不然你离开页面如果它没执行完就还会倒计时继续执行
    destroyed () {
    clearInterval(this.timer)
  }
  1. 倒计时之前的校验处理(手机号、验证码)

由于校验这个功能比较通用,所以我们可以把它封装成一个方法

  • 首先需要校验,那就需要先拿到这两个数据
  • 所以我们需要在data中准备变量
  • 准备了变量就记得在页面相应处v-model
  • 还可以优化比如用个toast轻提示
js 复制代码
mobile: '', // 手机号
picCode: '' // 请求用户输入的图形验证码
js 复制代码
   //methods中
   // 校验 手机号 和 图形验证码 是否合法
    validFn () {
      // 以1开头,第二位3-9,再后面\d{9},即再有9个数字
      if (!/^1[3-9]\d{9}$/.test(this.mobile)) {
        this.$toast('请输入正确的手机号')
        return false
      }
      if (!/^\w{4}$/.test(this.picCode)) {
        this.$toast('请输入正确的图形验证码')
        return false
      }
      // 只有上面两个都通过了校验,才return ture
      return true
    },
  • 写完上面这两个校验,就可以跟下面的短信验证码联动了
  • 如果上面没通过,就不用执行短信验证码了
js 复制代码
// 获取短信验证码
getCode () {
      if (!this.validFn()) {
        // 如果没通过校验,就不需要往下获取验短信证码了
        return
      }
 }
  1. 封装短信验证请求接口,发送请求添加提示

通过智慧商城的接口文档(登录-获取短信验证码),我们在自己的 api的login.js 里写上这个接口,之后页面调用一下就可以

js 复制代码
// 2. 获取短信验证码
export const getMsgCode = (captchaCode, captchaKey, mobile) => {
  return request.post('/captcha/sendSmsCaptcha', {
    form: {
      captchaCode,
      captchaKey,
      mobile
    }
  })
}

调用这个接口(在定时器倒计时方法处):

js 复制代码
 // 发送请求
const res = await getMsgCode(this.picCode, this.picKey, this.mobile)
onsole.log(res)

------------------------成功 \^o^/

看到 status: 200 就说明成功了!

在控制台看到成功后,就可以稍微修改一下代码,把log换成toast轻提示

js 复制代码
 await getMsgCode(this.picCode, this.picKey, this.mobile)
 this.$toast('短信验证成功!')

登录功能

目标:封装api登录接口,实现登录功能

  1. 通过智慧商城接口文档,封装登录接口
js 复制代码
// 3. 登录接口
export const codeLogin = (mobile, smsCode) => {
  return request.post('/passport/login', {
    form: {
      isParty: false,
      partyData: {},
      mobile,
      smsCode
    }
  })
}
  1. 登录前的校验
  2. 调用方法,发送请求,成功添加提示并跳转👇
js 复制代码
//data提供变量
msgCode:''// 短信验证码
// 输入框绑定
<input v-model="msgCode" class="inp" placeholder="请输入短信验证码" type="text">
// 先注册触发校验方法的点击事件
<div @click="login" class="login-btn">登录</div>
js 复制代码
import { codeLogin, getMsgCode, getPicCode } from '@/api/login'

 // 登录
    async login () {
      if (!this.validFn()) {
        return
      }
      if (!/^\d{6}$/.test(this.msgCode)) {
        this.$toast('请输入正确的短信验证码')
        return
      }
      // 如果这里的codeLogin显示没定义,就看上面import那里有没有从api那里导入这部分
      // 但其实你在拼写的时候,系统提示你然后你回车不全后,它上面会自动帮你加上
      const res = await codeLogin(this.mobile, this.msgCode)
      console.log(res)
      // 提示登录成功,并且跳转首页
      this.$toast('登录成功')
      this.$router.push('/')
    }
  },

默认密码:246810,成功\^o^/

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

相关推荐
前端小小王27 分钟前
React Hooks
前端·javascript·react.js
迷途小码农零零发37 分钟前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀1 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
旭东怪1 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
ekskef_sef3 小时前
32岁前端干了8年,是继续做前端开发,还是转其它工作
前端
sunshine6413 小时前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻4 小时前
Vue(四)
前端·javascript·vue.js
蜜獾云4 小时前
npm淘宝镜像
前端·npm·node.js
dz88i84 小时前
修改npm镜像源
前端·npm·node.js
Jiaberrr4 小时前
解锁 GitBook 的奥秘:从入门到精通之旅
前端·gitbook