【 Vue3 + Vite + setup语法糖 + Pinia + VueRouter + Element Plus 第四篇】(持续更新中)

news2024/11/17 10:25:07

在第三篇中,我们主要学习了组件的封装与使用以及 组件间传值Element Plus 表格、表单的用法

本期需要掌握的知识如下:

  • mixin 公共方法封装和使用
  • 项目中导入 VueRouter
  • 使用 VueRouter 完成 路由跳转、获取路由信息
  • VueRouter 模块化、路由拦截器
  • 权限路由配置

下期需要掌握的知识如下:

  • 项目中导入 Pinia
  • 使用 Pinia 完成登录存储用户信息,并在页面使用/调用 Pinia 方法/数据
  • 持久化 Pinia 数据
  • 路由拦截中使用 Pinia 代替 本地存储 Stroage

1. mixin公共方法封装

src目录下新建 mixin目录,并在该目录下新建 index.js
在这里插入图片描述

// 引入 element 弹窗提示组件
import { ElMessageBox } from 'element-plus'
// 引入进度条组件
import nprogress from "nprogress"
// 设置进度条loading样式
nprogress.configure({ showSpinner: false })

// 封装 弹窗确认组件
export const MessageBoxMixins = async tips => {
  try {
    let res = await ElMessageBox.confirm(tips, '提示', {
      confirmButtonText: '确认',
      cancelButtonText: '取消',
      type: 'warning'
    })
    return res
  } catch (err) {
    return err
  }
}
// 封装 localStorage 存储方法
export const setlocalstroage = (key, val) => {
  return localStorage.setItem(key, val)
}
export const setsessionstroage = (key, val) => {
  return sessionStorage.setItem(key, val)
}
// 封装 localStorage 设置方法
export const getlocalstroage = key => {
  return localStorage.getItem(key)
}
export const getsessionstroage = key => {
  return sessionStorage.getItem(key)
}
// 封装 sessionStorage 清除方法
export const clearSession = () => {
  sessionStorage.clear()
}
export const clearLocal = () => {
  return localStorage.clear()
}
// 封装 sessionStorage 清除某一项方法
export const removeSessionItem = key => {
  return sessionStorage.removeItem(key)
}
export const removeLocalItem = key => {
  return localStorage.removeItem(key)
}
// 封装 开启进度条方法
export const showNprogress = () => {
  nprogress.start()
}
// 封装 关闭进度条方法
export const hideNprogress = () => {
  nprogress.done()
}

2. vue-router 安装及配置

使用 npm i vue-router@4 安装 VueRouter

main.js

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
// 导入 router
import router from './router'

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'

import axios from 'axios'
import VueAxios from 'vue-axios'

// 在此使用 router
createApp(App).use(router).use(ElementPlus, { locale: zhCn }).use(VueAxios, axios).mount('#app')

创建模块化路由

目录结构如下

index.js为根路由,所有 modules下的路由都会在 index.js导入,并最终在 index.js合并后统一导出

注: 所有的模块化路由都建议放到 modules目录下,更具备语义化

在这里插入图片描述

home.js

// 导出 home 路由
export const homeRoutes = [
  {
    path: '/',
    // 访问项目根路径的时候会重定向到 /home
    // 下面会根据 token 判断用户是否登录,在拦截器中让它跳转登录页面
    redirect: '/home'
  },
  {
    name: 'home',
    path: '/home',
    // meta document 压面的 title 值, 也会在路由拦截器中进行配置
    meta: {
      title: '首页'
    },
    // 路由懒加载
    component: () => import('@/views/home/index.vue')
  },
  {
    name: 'list',
    path: '/list/:id',
    meta: {
      title: '列表页'
    },
    component: () => import('@/views/list/index.vue')
  },
  // 404 页面,当用户访问不存在的路由时跳转到该页面
  // 后面也会在路由拦截器中进行配置
  {
    name: '404 Not Found',
    path: '/404',
    meta: {
      title: '404 Not Found'
    },
    component: () => import('@/views/NotFound/index.vue')
  }
]

login.js

export const loginRoutes = [
  {
    name: 'login',
    path: '/login',
    meta: {
      title: '登录'
    },
    component: () => import('@/views/login/index.vue')
  }
]

模块化路由已经创建完毕,我们需要对index.js进行配置

// 引入创建路由 创建 history 路由方法
import { createRouter, createWebHistory } from 'vue-router'
// 引入 home 路由
import { homeRoutes } from './modules/home'
// 引入 login 路由
import { loginRoutes } from './modules/login'
// 封装的 mixin 公共方法
import { getlocalstroage, clearSession, clearLocal, showNprogress, hideNprogress } from '@/mixin'

// 首先把你需要动态路由的组件地址全部获取
let modules = import.meta.glob('../views/**/*.vue')
// 设置标识 防止路由进入死循环
let flag = true

// 创建 router 
const router = createRouter({
  history: createWebHistory(), // 设置为 history 模式
  routes: [...loginRoutes, ...homeRoutes] // 合并路由
})

// 路由拦截器 前置钩子函数
router.beforeEach((to, from, next) => {
// 开启进度条
  showNprogress()
  // 判断有无 title 给 页面标题设置
  if (to.meta.title) {
    document.title = to.meta.title
  }
  const data = [{
      "name": "admin",
      "path": "/admin",
      "hidden": false,
      "meta": {
        "title": "首页"
      },
      "children": [
        {
          "name": "admin/user",
          "path": "user",
          "hidden": false,
          "meta": {
            "title": "用户管理"
          }
        },
        {
          "name": "admin/role",
          "path": "role",
          "hidden": false,
          "meta": {
            "title": "角色管理"
          }
        }
      ]
    }]
   // 下期讲 Pinia 的时候这里的数据会替换成 Pinia 的数据
  if (data.length > 0) {
  	addDynamicRoute(data)
    if (flag) {
     // 这里添加匹配 404 路由模式,必须在静态路由中先加上 /404 页面
      const NotFound = { path: '/:pathMatch(.*)*', redirect: '/404' }
      // 添加 404 路由页面
      router.addRoute(NotFound)
      // 这里是必须的 解决 Vue3 中 刷新页面导致路由失效问题
      next({ ...to, replace: true })
      // 添加 router.options 只有添加了再能回去 下面我们会讲
      router.options.routes.push(JSON.parse(JSON.stringify(...animationRoute.value),NotFound))
      // 设置 falg 为 false 下次路由刷新将不会进入该循环 以防造成死循环
      flag = false
    }
  }
  // 因 login 页面不需要 token 就可以访问,所以我们在此判断
  if (to.path != '/login') {
  	// 获取 token
    let apiToken = getlocalstroage('user') ? JSON.parse(getlocalstroage('user')) : null
    if (!apiToken) {
      // 如果没有 token 清除掉存储并跳转 login 页面
      clearSession()
      clearLocal()
      next('/login')
    }
  }
  // 反之则放行
  next()
})

// 路由后置钩子  在此关闭进度条
router.afterEach(() => {
  hideNprogress()
})

// 添加动态路由,parent默认为home是首页最外层的路由name名
const addDynamicRoute = (useroute, parent) => {
  for (let i = 0; i < useroute.length; i++) {
    if (useroute[i].children && useroute[i].children.length > 0) {
      // 如果有嵌套路由 router.addRoute 接收的第一个参数为父组件 name 值
      // 如果不是 则不传
      router.addRoute({ name: useroute[i].name, path: useroute[i].path, component: modules[`../views/${useroute[i].name}/index.vue`], meta: { title: useroute[i].meta.title }, hidden: useroute[i].hidden })
      // 递归添加动态路由
      addDynamicRoute(useroute[i].children, useroute[i].name);
    } else {
      router.addRoute(parent, { path: useroute[i].path, component: modules[`../views/${useroute[i].name}/index.vue`], meta: { title: useroute[i].meta.title }, hidden: useroute[i].hidden })
    }
  }
};

// 导出 router
export default router

注意此处有大坑

  1. Vue3 中的 嵌套路由前不能携带 / ,否则解析不成功
  2. 动态设置的路由必须 router.options.routes.push添加进去,否则在页面使用获取不到动态路由信息
  3. router.addRoute()方法使用后必须 next({ ...to, replace: true }) ,否则刷新后动态路由消失
  4. { path: '/:pathMatch(.*)*', redirect: '/404' }必须在最后添加该路由,否则匹配不到此路由后的路由

3. 路由在页面的使用

// 最简单的方法 在需要的页面导入 useRouter 方法
import { useRouter } from 'vue-router'
const Router = useRouter() // useRouter 是一个方法 使用 Router 接收它
// 页面加载完毕钩子函数
onMounted(() => {
  console.log(Router)
})

在这里插入图片描述
我们可以看到路由的所有方法都会在这里体现

console.log(Router.currentRoute._value) // 获取当前路由信息
console.log(Router.currentRoute._value.query) // 获取 ? 后传入的参数
console.log(Router.currentRoute._value.params) // 获取 :路径配置的参数 同 Vue2
Router.push('/home') // 路由跳转
Router.go(-1) // 路由回退
console.log(Router.options) // 获取所有路由的配置信息,如果你设置了动态路由但是并没有 push 到 options 里的话,这里是获取不到的

Vue3 篇幅完结之后我们会上传相对应的免费源码,以供二次开发的使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/149800.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

https 加密原理握手过程详解

HTTPS握手过程 HTTPS的握手过程比较繁琐&#xff0c;我们来回顾下。 先是建立TCP连接&#xff0c;毕竟HTTP是基于TCP的应用层协议。 在TCP成功建立完协议后&#xff0c;就可以开始进入HTTPS阶段。 HTTPS可以用TLS或者SSL啥的进行加密&#xff0c;下面我们以TLS1.2为例。 总…

自定义antd或element table 列设置组件(拖拽排序及控制是否展示)

需求 展示出所有的字段显示当前展示的是哪些字段可以全选、取消全选可以拖拽排序&#xff0c;更改字段的展示顺序&#xff0c;在前面还是在后面可以保存配置&#xff0c;刷新不失效 难点 如何进行拖拽排序&#xff0c;自己手写一个吗&#xff1f;如何得到拖拽后的顺序&#…

verilog学习笔记- 8)状态机

目录 概念&#xff1a; 状态机的模型&#xff1a; 状态机的设计&#xff1a; 根据状态机的实际写法&#xff0c;状态机可以分为一段式、二段式和三段式状态机。 三段式状态机的基本格式&#xff1a; 概念&#xff1a; 状态机&#xff0c;全称是有限状态机&#xff08;Fin…

再学C语言29:函数——概述

C的设计原则是把函数作为程序的构成模块 函数&#xff08;function&#xff09;&#xff1a;用于完成特定任务的程序代码的自包含单元 使用函数的好处&#xff1a; 1&#xff09;函数的使用可以省去重复代码的编写&#xff0c;尤其是程序中需要多次使用某种特定的功能时&…

unity日记4(鼠标键盘交互、实例)

目录 鼠标事件 鼠标点击、抬起、长按事件 键盘事件 键盘点击、抬起、长按事件 键盘键位替换 实例&#xff1a;鼠标-音乐播放/暂停 实例&#xff1a;调用其他对象的组件&#xff08;双方法&#xff09; 实例&#xff1a;调整其他对象的公有参数 鼠标事件 鼠标点击、抬起、长…

实体关系抽取

关系抽取分为pipeline型和联合&#xff08;Joint&#xff09;抽取。 pipeline形式&#xff1a; 指把关系抽取&#xff0c;拆分成多个任务&#xff0c;如【先抽Subject&#xff0c;再一起抽Predict和Object】&#xff08;CasRel&#xff09;、【先判断Predict&#xff0c;再一…

『博客专家』- 你申请了吗?

目录为什么要申请专家博客&#xff1f;个人申请专家博客的流程&#xff1f;个人申请经历7月20日7月20日7月22日7月27日8月2日8月7日8月9日9月26日10月23日10月28日【补】12月5日【补】12月23日总结提一盏读书灯,去翻山越岭; 为什么要申请专家博客&#xff1f; 每次看到厉害的博…

Java中ArrayList如何删除指定位置的元素

目标&#xff1a;list中有0到39共40个元素&#xff0c;删除其中索引是10、20、30的元素 方案一&#xff1a;使用普通for循环从前往后遍历再删除 初始化List列表 List<String> list new ArrayList<>(); for (int i 0; i < 40; i) {list.add("element&qu…

Leetcode 剑指 Offer II 009. 乘积小于 K 的子数组

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给定一个正整数数组 nums 和整数 k &#xff0c;请找出该数组内乘…

处方眼镜镜片在线定制类跨境电商独立站怎么做?

对于处方眼镜镜片&#xff0c;有很多的参数&#xff0c;对于在线类跨境电商商城&#xff0c;需要用户一步一步的提交很多的眼镜参数&#xff0c;下面是fecify眼镜镜片参数的定制过程, fecify的眼镜定制插件提供强有力的支持&#xff0c;下面是处方眼镜镜片在线定制类跨境电商独…

为什么Windows错误报告叫作Dr. Watson?

应该有一部分人可能会知道&#xff0c;Windows 错误报告有一个昵称&#xff0c;叫做”Dr. Watson”(华生医生)&#xff0c;没事&#xff0c;你不知道&#xff0c;也没关系。 今天的文章主要是讲讲&#xff0c;这个”Dr. Watson”名称的来历。 和你所猜想的一样&#xff0c;Dr.…

Java高手速成 | Java集合类泛类型

Java高手是这样炼成的。 01、Java集合类包括哪些&#xff1f; 作为学习集合类泛类型的预备知识&#xff0c;图1列出了Java集合类继承图。要学会集合类泛类型&#xff0c;除了懂得集合类外&#xff0c;大家也需 要了解继承的工作原理。图中虚线表示Collection是一个接口。 02…

Java-性能分析监控工具

Java监控和管理 Java监控和管理API Java Standard Edition&#xff08;Java SE&#xff09;平台提供的监控和管理技术 - JMX&#xff08;Java Management Extensions&#xff09; 技术。 Java SE 中包含了用于监控和管理的&#xff08;java.lang.management&#xff09;API&…

RabbitMQ 总结一(简介、安装、Demo)

目录 什么是MQ RabbitMQ和netty是什么关系 作用 流量削峰 应用解耦 异步处理 MQ的构成 生产者 交换机 队列 消费者 下载安装 案例Demo producer 第一步&#xff0c; 定义好连接的信息并且拿到连接&#xff0c;一般一个consumer/ producer 和broker只会建立一条连…

mysql之日志

前言 一条数据在更新过程当中&#xff0c;如果中途 mysql crash 了&#xff0c;mysql 是如何保证数据的一致性和持久性的&#xff1f;在这个过程中 mysql 的日志系统起到了至关重要的作用。本文将会介绍 mysql 中的 undo log、redo log 和 bin log 在这其中的作用。 buffer p…

230109-MacOS解决brew安装慢的问题

MacOS解决brew安装慢的问题 原文请移步参考&#xff1a; https://www.zhihu.com/question/46963138 cd "$(brew --repo)" git remote set-url origin https://mirrors.ustc.edu.cn/brew.gitecho export HOMEBREW_BOTTLE_DOMAINhttps://mirrors.ustc.edu.cn/homebrew…

2022年度大赏 | UWA问答精选

UWA每周推送的知识型栏目《厚积薄发 | 技术分享》已经伴随大家走过了304个工作周。精选了2022年十大精彩问答分享给大家&#xff0c;期待2022年UWA问答继续有您的陪伴。 Q1&#xff1a;动态获取URP设置里自定义的RenderFeatures 我们在URP项目中自定义了多个RenderFeatures去实…

2022年度总结,以及2023的全新展望

时光总是在你的不经意间流逝&#xff0c;无法挽留&#xff1b;留得住的是你过去的努力和回忆&#xff0c;它也许充斥着快乐、忧伤、病痛等等。俗话说得好“笑一笑十年少”&#xff0c;那么我希望与快乐随行&#xff0c;让痛苦尘封记忆。让我们总结过去&#xff0c;展望未来&…

Python tkinter -- 第18章 画布控件之矩形

18.2.20 create_rectangle(bbox, **options) 根据限定矩形 bbox&#xff0c;在画布上创建一个矩形。新创建的对象位于显示的最前端。 &#xff08;1&#xff09;bbox&#xff1a;定义要创建对象的边界(x1, y1, x2, y2) &#xff08;2&#xff09;options&#xff1a; 选项的具体…

ICESat数据下载

ICESat数据下载1. ICESat简介2. ICESat数据产品2.1 GLA01数据2.2 GLA14数据3. 数据下载4. 总结1. ICESat简介 2003年美国国家航空航天局NASA ( National Aeronautics and SpaceAdministration)发射冰、云和陆地高程卫星ICESat&#xff0c;其上搭载的地球科学激光测高系统GLAS是…