移动端面经项目(2)--路由设计与封装,主体定制,vant组件库的进一步学习,登录与注册功能的实现,利用原先封装的token方法与路由守卫实现页面访问拦截

当前项目进度已经上传到gitee开源远程仓库: https://gitee.com/Scurryniubi/project_mj
SSH码: git@gitee.com:Scurryniubi/project_mj.git

路由设计配置

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

路由设计:

  • 登录页 (一级) login

  • 注册页(一级) register

  • 文章详情页(一级) detail

  • 首页(一级) layout

  • 面经(二级)article

  • 收藏(二级)collect

  • 喜欢(二级)like

  • 我的(二级)my

一级路由

router/index.js配置一级路由

import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '@/views/login'
import Register from '@/views/register'
import Detail from '@/views/detail'
import Layout from '@/views/layout'
Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    { path: '/login', component: Login },
    { path: '/register', component: Register },
    { path: '/article/:id', component: Detail },
    {
      path: '/',
      component: Layout
    }
  ]
})

export default router

清理 App.vue

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<script>
export default {
  async created () {

  }
}
</script>

tabbar标签页

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

main.js 引入组件

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

layout.vue

<template>
  <div class="layout-page">
    首页架子 - 内容区域

    <van-tabbar>
      <van-tabbar-item icon="notes-o">面经</van-tabbar-item>
      <van-tabbar-item icon="star-o">收藏</van-tabbar-item>
      <van-tabbar-item icon="like-o">喜欢</van-tabbar-item>
      <van-tabbar-item icon="user-o">我的</van-tabbar-item>
    </van-tabbar>
  </div>
</template>

二级路由

router/index.js配置二级路由

import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '@/views/login'
import Register from '@/views/register'
import Detail from '@/views/detail'
import Layout from '@/views/layout'

import Like from '@/views/like'
import Article from '@/views/article'
import Collect from '@/views/collect'
import User from '@/views/user'
Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    { path: '/login', component: Login },
    { path: '/register', component: Register },
    { path: '/article/:id', component: Detail },
    {
      path: '/',
      component: Layout,
      redirect: '/article',
      children: [
        { path: '/article', component: Article },
        { path: '/like', component: Like },
        { path: '/collect', component: Collect },
        { path: '/user', component: User }
      ]
    }
  ]
})

export default router

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

<template>
  <div class="layout-page">
    <router-view></router-view>

    <van-tabbar route>
      <van-tabbar-item to="/article" icon="notes-o">面经</van-tabbar-item>
      <van-tabbar-item to="/collect" icon="star-o">收藏</van-tabbar-item>
      <van-tabbar-item to="/like" icon="like-o">喜欢</van-tabbar-item>
      <van-tabbar-item to="/user" icon="user-o">我的</van-tabbar-item>
    </van-tabbar>
  </div>
</template>

效果图:

主题定制

整体网站风格,其实都是橙色的,可以通过变量覆盖的方式,制定主题色

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

babel.config.js 制定样式路径

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
  plugins: [
    ['import', {
      libraryName: 'vant',
      libraryDirectory: 'es',
      // 指定样式路径
      style: (name) => `${name}/style/less`
    }, 'vant']
  ]
}

vue.config.js 覆盖变量

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  css: {
    loaderOptions: {
      less: {
        lessOptions: {
          modifyVars: {
            // 直接覆盖变量
            blue: 'red'
          },
        },
      },
    },
  },
})

重启服务器生效!

效果如图所示:

登录&注册功能

登录静态布局

使用组件

  • van-nav-bar

  • van-form

  • van-field

  • van-button

vant-ui.js 注册

import Vue from 'vue'
import {
  NavBar,
  Form,
  Field
} from 'vant'
Vue.use(NavBar)
Vue.use(Form)
Vue.use(Field)

login.vue 使用

结合正则表达式进行校验
同时注意将name中的中文换成英文,以方便更好地在获取对象时使用
<template>
  <div class="login-page">
    <!-- 导航栏部分 -->
    <van-nav-bar title="面经登录" />

    <!-- 一旦form表单提交了,就会触发submit,可以在submit事件中
         根据拿到的表单提交信息,发送axios请求
     -->
    <van-form @submit="onSubmit">
      <!-- 输入框组件 -->
      <!-- \w 字母数字_   \d 数字0-9 -->
      <van-field
        v-model="username"
        name="username"
        label="用户名"
        placeholder="用户名"
        :rules="[
          { required: true, message: '请填写用户名' },
          { pattern: /^\w{5,}$/, message: '用户名至少包含5个字符' }
        ]"
      />
      <van-field
        v-model="password"
        type="password"
        name="password"
        label="密码"
        placeholder="密码"
        :rules="[
          { required: true, message: '请填写密码' },
          { pattern: /^\w{6,}$/, message: '密码至少包含6个字符' }
        ]"
      />
      <div style="margin: 16px">
        <van-button block type="info" native-type="submit">提交</van-button>
      </div>
    </van-form>
  </div>
</template>

<script>
export default {
  name: 'login-page',
  data () {
    return {
      username: 'zhousg',
      password: '123456'
    }
  },
  methods: {
    onSubmit (values) {
      console.log('submit', values)
    }
  }
}
</script>

login.vue添加 router-link 标签(跳转到注册)

<template>
  <div class="login-page">
    <van-nav-bar title="面经登录" />

    <van-form @submit="onSubmit">
      ...
    </van-form>
    
    <router-link class="link" to="/register">注册账号</router-link>
  </div>
</template>

login.vue调整样式

<style lang="less" scoped>
.link {
  color: #069;
  font-size: 12px;
  padding-right: 20px;
  float: right;
}
</style>

注册静态布局

register.vue

<template>
  <div class="login-page">
    <van-nav-bar title="面经注册" />

    <van-form @submit="onSubmit">
      <van-field
        v-model="username"
        name="username"
        label="用户名"
        placeholder="用户名"
        :rules="[{ required: true, message: '请填写用户名' }]"
      />
      <van-field
        v-model="password"
        type="password"
        name="password"
        label="密码"
        placeholder="密码"
        :rules="[{ required: true, message: '请填写密码' }]"
      />
      <div style="margin: 16px">
        <van-button block type="primary" native-type="submit"
          >注册</van-button
        >
      </div>
    </van-form>
    <router-link class="link" to="/login">有账号,去登录</router-link>
  </div>
</template>

<script>
export default {
  name: 'register-page',
  data () {
    return {
      username: '',
      password: ''
    }
  },
  methods: {
    onSubmit (values) {
      console.log('submit', values)
    }
  }
}
</script>

<style lang="less" scoped>
.link {
  color: #069;
  font-size: 12px;
  padding-right: 20px;
  float: right;
}
</style>

toast 轻提示

将来无论注册成功,还是失败,都是需要给用户提示的

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

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

两种使用方式

  1. 导入,调用

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

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

封装api接口 - 注册功能(axios)

新建 api/user.js 提供注册 Api 函数

import request from '@/utils/request'

// 注册接口
export const register = (data) => {
  return request.post('/user/register', data)
}

register.vue页面中调用测试

methods: {
  async onSubmit (values) {
    // 往后台发送注册请求了
    await register(values)
    this.$toast.success('注册成功')
    this.$router.push('/login')
  }
}

request.js响应拦截器,统一处理错误提示

import { Toast } from 'vant'

...

// 添加响应拦截器
request.interceptors.response.use(function (response) {
  // 对响应数据做点什么
  return response.data
}, function (error) {
  if (error.response) {
    // 有错误响应, 提示错误提示
    Toast(error.response.data.message)
  }
  // 对响应错误做点什么
  return Promise.reject(error)
})

封装api接口 - 登录功能

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

// 登录接口
export const login = (data) => {
  return request.post('/user/login', data)
}

login.vue 登录功能

import { login } from '@/api/user'
import { setToken } from '@/utils/storage'

methods: {
  async onSubmit (values) {
    const { data } = await login(values)
    setToken(data.token)
    this.$toast.success('登录成功')
    this.$router.push('/')
  }
}

页面访问拦截

这个 面经移动端 项目,只对 登录用户 开放,如果未登录,一律拦截到登录

  1. 如果访问的是 首页, 无token, 拦走

  1. 如果访问的是 列表页,无token, 拦走

  1. 如果访问的是 详情页,无token, 拦走

....

分析:哪些页面,是不需要登录,就可以访问的! => 注册登录 (白名单 - 游客可以随意访问的)

核心逻辑:

  1. 判断用户有没有token, 有token, 直接放行

  1. 没有token(游客),如果是白名单中的页面,直接放行

  1. 否则,无token(游客),且在访问需要权限访问的页面,直接拦截到登录

vue路由内置了一个语法

全局前置守卫:

可以在vue2官网中的路由相关文档中了解到更多详细的信息
  1. 所有的路由一旦被匹配到,在真正渲染解析之前,都会先经过全局前置守卫

  1. 只有全局前置守卫放行,才能看到真正的页面

// 全局前置守卫:
// 1. 所有的路由一旦被匹配到,在真正渲染解析之前,都会先经过全局前置守卫
// 2. 只有全局前置守卫放行,才能看到真正的页面

// 任何路由,被解析访问前,都会先执行这个回调
// 1. from 你从哪里来, 从哪来的路由信息对象
// 2. to   你往哪里去, 到哪去的路由信息对象
// 3. next() 是否放行,如果next()调用,就是放行 => 放你去想去的页面
//    next(路径) 拦截到某个路径页面

const whiteList = ['/login', '/register'] // 白名单列表,记录无需权限访问的所有页面

router.beforeEach((to, from, next) => {
  const token = getToken()
  // 如果有token,直接放行
  if (token) {
    next()
  } else {
    // 没有token的人, 看看你要去哪
    // (1) 访问的是无需授权的页面(白名单),也是放行
    //     就是判断,访问的地址,是否在白名单数组中存在 includes
    if (whiteList.includes(to.path)) {
      next()
    } else {
      // (2) 否则拦截到登录
      next('/login')
    }
  }
})
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值