vue学习106-120

创建项目p106


router,store和app.vue不用删
清一下router里的路由配置

vant组件库p107

目标:认识第三方vue组件库vant-ui(cv战士)
封装好了的组件整合在一起就是组件库
http://vant-contrib.gitee.io/vant/v2/#/zh-CN/
vue2用vant2,vue3用vant3和4
在这里插入图片描述
vant全部导入太慢了,按需导入推荐
安装npm i vant@latest-v2 -S
阿里云安装镜像 npm config set registry https://registry.npmmirror.com/

引入

vant网址http://vant-contrib.gitee.io/vant/v2/#/zh-CN/quickstart
cv到main.js
方式一. 自动按需引入组件 (推荐)
babel-plugin-import 是一款 babel 插件,它会在编译过程中将 import 的写法自动转换为按需引入的方式。

###### 安装插件
npm i babel-plugin-import -D
// 在.babelrc 中添加配置
// 注意:webpack 1 无需设置 libraryDirectory
{
  "plugins": [
    ["import", {
      "libraryName": "vant",
      "libraryDirectory": "es",
      "style": true
    }]
  ]
}

// 对于使用 babel7 的用户,可以在 babel.config.js 中配置
module.exports = {
  plugins: [
    ['import', {
      libraryName: 'vant',
      libraryDirectory: 'es',
      style: true
    }, 'vant']
  ]
};
// 接着你可以在代码中直接引入 Vant 组件
// 插件会自动将代码转化为方式二中的按需引入形式
import { Button } from 'vant';

Tips: 如果你在使用 TypeScript,可以使用 ts-import-plugin 实现按需引入。

方式二. 手动按需引入组件(要css,不推荐)
在不使用插件的情况下,可以手动引入需要的组件。

import Button from 'vant/lib/button';
import 'vant/lib/button/style';

方式三. 导入所有组件
Vant 支持一次性导入所有组件,引入所有组件会增加代码包体积,因此不推荐这种做法。

import Vue from 'vue';
import Vant from 'vant';
import 'vant/lib/index.css';
//插件安装初始化,内部将所有的vant组件进行导入注册
Vue.use(Vant);

Tips: 配置按需引入后,将不允许直接导入所有组件。

按需导入


安装插件每次都要重新弄npm i babel-plugin-import -D

module.exports = {
  plugins: [
    ['import', {
      libraryName: 'vant',
      libraryDirectory: 'es',
      style: true
    }, 'vant']
  ]
};

在这里插入图片描述
放main.js里太多了,导入组件单独分一个vant-ui.js放在utils文件夹里
如果渲染不出来,重新打开编程软件和终端
在这里插入图片描述

postcss插件-实现vw适配p108

postcss写多少px直接转换为多少vw
在这里插入图片描述
npm下载插件:npm install postcss-px-to-viewport@1.1.1 -D --force//npm install postcss-px-to-viewport --legacy-peer-deps/
要在根目录上(和src同级的)创建postcss.config.js
然后官网cv:

// postcss.config.js
module.exports = {
  plugins: {
    'postcss-px-to-viewport': {
      viewportWidth: 375,
    },
  },
};

在这里插入图片描述

路由设计配置p109

一级路由配置

单个页面独立展示的是一级路由
在这里插入图片描述
每个一级路由要建成一个文件夹
在这里插入图片描述
文件夹里只有一个时直接简写文件夹
path中表示首页的是/

二级路由-底部导航tabbar

vant组件库有
在这里插入图片描述
vant2里有基础组件-icon图标
tabber标签栏-自定义颜色
在这里插入图片描述
点击切换用vant2的路由模式
在这里插入图片描述
默认首页在routes里加redirect
在这里插入图片描述
在这里插入图片描述

登录页静态布局+图形验证码功能p110

在这里插入图片描述

头部navbar

通用样式覆盖
在这里插入图片描述

request模块-axios封装-13min

使用axios请求后端接口,单独封装到一个request模块
request模块放在utils/request.js文件里
接口文档地址: https://apifox.com/apidoc/shared-12ab6b18-adc2-444c-ad11-0e60f5693f66/doc-2221080
基地址:http://cba.itlike.com/public/index.php?s=/api/
request文件里面放axios官方文档-axios实例(https://www.axios-http.cn/docs/instance)
在这里插入图片描述

  1. 创建axios实例
    创建axios实例不会污染原始的axios实例,如果触及就会改底层参数
  2. 自定义配置-请求/响应 拦截器
添加请求拦截器

给原本axios实例加配置,没加到创建的实例上,要想不污染原始,就改成instance(创建的axios实例上)
在这里插入图片描述
axios的接口文档要从智慧商城找(http://cba.itlike.com/public/index.php?s=/api/)

const instance = axios.create({
  baseURL: 'https://some-domain.com/api/',//接口文档地址
  timeout: 1000,//超时时间
  headers: {'X-Custom-Header': 'foobar'}//这个没用
});

在这里插入图片描述

添加响应拦截器

在这里插入图片描述

导出配置好的实例(instance)

获取图片验证码数据结构,要复制地址

  1. base64:图片
  2. key:唯一标识
  3. md5:验证
    在这里插入图片描述

图形验证码

在这里插入图片描述

获取短信验证码-39min

前两个缺一不可
4. captchacode 图形验证码值
5. captchakey验证码的唯一标识
6. mobile手机号
在这里插入图片描述

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

api模块(存放封装好的请求函数)
以前的模式

  1. 页面请求代码太多,可阅读性不高
  2. 相同请求没有复用
  3. 请求没有统一管理
    封装api模块的好处
  4. 请求与页面逻辑分离
  5. 相同的请求可以直接复用
  6. 请求进行了统一管理
    在这里插入图片描述

toast轻提示p112

在这里插入图片描述
点击出现轻提示
在这里插入图片描述
进入页面出现轻提示
在这里插入图片描述
this.$toast()只能用在实例组件里
在这里插入图片描述

短信验证倒计时p113

在这里插入图片描述
totalSecond和second要一致
封装短信验证请求接口智慧商城里
import { getMsgCode } from '@/api/login’别忘了导入

<template>
  <div class="login" @click="getPicCode">
    <button>wds</button>
    <input type="number">
    <button @click="getCode">{{ second===totalSecond? '获取验证码':second+'秒后重新发送'}}</button>
  </div>
</template>

<script>
import { getMsgCode } from '@/api/login'

export default {
  name: 'login-page',
  data () {
    return {
      picKey: '',
      picUrl: '',
      totalSecond: 6, // 总秒数
      second: 6, // 当前秒数
      timer: null, // 定时器id
      mobile: '', // 手机号
      picCode: ''// 用户输入的图形验证码
    }
  },
  methods: {
    // 获取图片验证码
    async getPicCode () {
      // Toast('获取图形验证码成功')
      this.$toast('wdf')
    },
    // 校验手机号和图形验证码是否合法
    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
    },
    // 获取验证码
    async getCode () {
      if (!this.validFn()) {
        return
      }
      // 当前没有定时器开着,且totalsecond和second一致(秒数归位)才可以倒计时
      if (!this.timer && this.totalSecond === this.second) {
        // 发送请求
        await getMsgCode(this.captchaCode, this.captchaKey, this.mobile)
        // 开启倒计时
        setInterval(() => {
          this.second--
          if (this.second <= 0) {
            clearInterval(this.timer)
            this.timer = null// 重置定时器id
            this.second = this.totalSecond// 归位
          }
        }, 1000)
      }
    }

  },
  destroyed () {
    clearInterval(this.timer)// 离开页面清除定时器
  }
}
</script>

<style>

</style>

响应拦截处理器-统一处理错误p115

status

// 添加响应拦截器
instance.interceptors.response.use(function (response) {
  // 2xx 范围内的状态码都会触发该函数。
  // 对响应数据做点什么(默认axios会多包装一层data,需要响应拦截器中处理一下)
  const res = response.data
  if (res.status !== 200) {
    // 给提示
    Toast(res.message)
    // 抛出一个错误的promise
    return Promise.reject(res.message)
  }
  return response.data
}, function (error) {
  // 超出 2xx 范围的状态码都会触发该函数。
  // 对响应错误做点什么
  return Promise.reject(error)
})

在这里插入图片描述

登录权证信息存储token和userld(user模块)/将token权证信息存入vuexP116

user模块放在store下面
在这里插入图片描述
在这里插入图片描述

export default {
  namespaced: true,
  // 提供数据
  state () {
    return {
      // 个人权证相关
      userInfo: {
        token: '',
        userId: ''
      }
    }
  },
  // 提供修改数据的方法的
  mutations: {},
  // 提供异步操作
  actions: {},
  // 提供基于state派生出来的属性
  getters: {}
}

storage存储模块-vuex持久化处理P117

vuex刷新会丢失,storage模块放utils里

// 约定一个通用的键名
const INFO_KEY = 'hm-shopping-info'

// 获取个人信息
export const getInfo = () => {
  const defultObj = { token: '', userId: '' }
  const result = localStorage.getItem(INFO_KEY)
  return result ? JSON.parse(result) : defultObj
}

// 设置个人信息
export const setInfo = (obj) => {
  localStorage.setItem(INFO_KEY, JSON.stringify(obj))
}

// 移除个人信息
export const removeInfo = () => {
  localStorage.removeItemItem(INFO_KEY)
}

import { getInfo, setInfo } from '@/utils/storage'

export default {
  namespaced: true,
  // 提供数据
  state () {
    return {
      // 个人权证相关
      userInfo: getInfo
    }
  },
  // 提供修改数据的方法的
  mutations: {
    // 所有mutations的第一个参数,都是state
    setUserInfo (state, obj) {
      state.userInfo = obj
      setInfo(obj)
    }
  },
  // 提供异步操作
  actions: {},
  // 提供基于state派生出来的属性
  getters: {}
}

添加请求loading效果P118

toast轻提示中的加载提示
在这里插入图片描述

页面访问拦截p119

在这里插入图片描述

// 所有的路由在真正访问到之前,都会经过全局前置守卫
// 只有全局前置守卫放行了,才能到达对应的页面

// 全局前置导航守卫
// to:到哪里去,到哪去的完整路由信息对象(路径,参数)
// from:到哪里来,从哪来的完整路由信息对象(路径,参数)
// next:是否放行
// (1)next()直接放行,放行到to要去的路径
// (2)next(路径)进行拦截,拦截到next里面配置的路径
router.beforeEach((to, from, next) => {
  // ...
  // 返回 false 以取消导航
  return false
})

在这里插入图片描述

// 定义一个数组,专门用户存放所有需要权限访问的页面
const authUrls= ['']

router.beforeEach((to, from, next) => {
  // ...
  // 返回 false 以取消导航
  // return false
  if (!authUrls.includes(to.path)) {
    // 非权限页面,直接放行
    next()
    return
  }
  // 是权限页面,需要判断token
  const token = store.getters.token
  if (token) {
    next()
  } else {
    next('/login')
  }
})
getters: {
    token (state) {
      return state.user.userInfo.token
    }
  },

首页-静态页面结构准备&动态渲染P120

  1. 静态结构准备(直接cv)
<template>
    <div class="home">
      <!-- 导航条 -->
      <van-nav-bar title="智慧商城" fixed />

      <!-- 搜索框 -->
      <van-search
        readonly
        shape="round"
        background="#f1f1f2"
        placeholder="请在此输入搜索关键词"
        @click="$router.push('/search')"
      />

      <!-- 轮播图 -->
      <van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
        <van-swipe-item>
          <img src="@/assets/banner1.jpg" alt="">
        </van-swipe-item>
        <van-swipe-item>
          <img src="@/assets/banner2.jpg" alt="">
        </van-swipe-item>
        <van-swipe-item>
          <img src="@/assets/banner3.jpg" alt="">
        </van-swipe-item>
      </van-swipe>

      <!-- 导航 -->
      <van-grid column-num="5" icon-size="40">
        <van-grid-item
          v-for="item in 10" :key="item"
          icon="http://cba.itlike.com/public/uploads/10001/20230320/58a7c1f62df4cb1eb47fe83ff0e566e6.png"
          text="新品首发"
          @click="$router.push('/category')"
        />
      </van-grid>

      <!-- 主会场 -->
      <div class="main">
        <img src="@/assets/main.png" alt="">
      </div>

      <!-- 猜你喜欢 -->
      <div class="guess">
        <p class="guess-title">—— 猜你喜欢 ——</p>

        <div class="goods-list">
          <GoodsItem v-for="item in 10" :key="item"></GoodsItem>
        </div>
      </div>
    </div>
  </template>

<script>
import GoodsItem from '@/components/GoodsItem.vue'
export default {
  name: 'HomePage',
  components: {
    GoodsItem
  }
}
</script>

  <style lang="less" scoped>
  // 主题 padding
  .home {
    padding-top: 100px;
    padding-bottom: 50px;
  }

  // 导航条样式定制
  .van-nav-bar {
    z-index: 999;
    background-color: #c21401;
    ::v-deep .van-nav-bar__title {
      color: #fff;
    }
  }

  // 搜索框样式定制
  .van-search {
    position: fixed;
    width: 100%;
    top: 46px;
    z-index: 999;
  }

  // 分类导航部分
  .my-swipe .van-swipe-item {
    height: 185px;
    color: #fff;
    font-size: 20px;
    text-align: center;
    background-color: #39a9ed;
  }
  .my-swipe .van-swipe-item img {
    width: 100%;
    height: 185px;
  }

  // 主会场
  .main img {
    display: block;
    width: 100%;
  }

  // 猜你喜欢
  .guess .guess-title {
    height: 40px;
    line-height: 40px;
    text-align: center;
  }

  // 商品样式
  .goods-list {
    background-color: #f6f6f6;
  }
  </style>

还要导入
在这里插入图片描述
2. 封装接口
导入api
在这里插入图片描述

  • 21
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值