51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Vue笔记[五]-路由

QX-AI
GPT-4
QX-AI初始化中...
暂无预设简介,请点击下方生成AI简介按钮。
介绍自己
生成预设简介
推荐相关文章
生成AI简介

路由route {#路由route}

前端路由用于实现 SPA应用(单页Web应用)

SPA应用:
(1) 整个应用只有一个完整的页面
(2) 点击导航区不刷新页面,只做页面的局部更新
(3) 数据需要通过 ajax 请求获取

每个路由都是路径组件映射关系,当浏览器的路径改变时,对应的组件就会显示

路由基本使用 {#路由基本使用}

在 Vue 中使用路由需安装 vue-router 插件

安装: npm install vue-router ,最新版本仅支持 Vue3,Vue2 需使用 vue-router@3

使用步骤:
(1) 创建路由器
(2) 注册路由
(3) 使用路由
(4) 编写路由组件

注意:
(1) 不断切换路由时,路由组件在重复地销毁和挂载,即重复地 经过完整的生命周期
(2) vue-router 插件会向 vm 和 vc 身上添加 $route(当前路由) 和 $router(全局路由器) 两个属性

1、创建路由器:
通常在 src 目录下新建 router/index.js

使用 new VueRouter() 创建路由器实例 /router/index.js

|------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // 该文件用于创建路由器 import VueRouter from 'vue-router'; import About from '@/pages/About.vue'; import Home from '@/pages/Home.vue'; // 创建路由器 export default new VueRouter({ routes: [ // 一级路由 { // 路由的路径 path: '/about', // 路由对应展示的组件 component: About }, { path: '/home', component: Home, }, ] }); |

2、注册路由:
new Vue() 时传入刚刚创建好的路由器实例

因为 vue-router 是插件,还要 Vue.use() 安装插件 main.js

|---------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import Vue from "vue"; import App from "./App.vue"; import VueRouter from "vue-router"; // 引入路由器 import router from "@/router" Vue.config.productionTip = false; Vue.use(VueRouter) new Vue({ el: "#app", render: h => h(App), // 使用路由器 router, }) |

3、使用路由:
vue-router 提供了几个特殊标签来使用路由

<router-link> 会被解析为 A 标签,点击后切换路由
<router-view> 指定路由组件的呈现位置 App.vue

|------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 | <template> <div> <!-- 使用router-link标签进行route切换 --> <router-link to="/home" active-class="active">Home</router-link> <router-link to="/about" active-class="active">About</router-link> <!-- 路由组件呈现位置 --> <router-view></router-view> </div> </template> <!-- ....... --> |

4、编写路由组件:
一般组件: 直接在另一个组件模板中写组件标签,一般放在 components 文件夹
路由组件: 配置在路由器中,通过切换路由动态展示和销毁,一般放在 pages 文件夹 /pages/Home.vue

|---------------------|-----------------------------------------------------------------------------| | 1 2 3 4 5 6 | <template> <div> <h2>我是Home组件</h2> </div> </template> <!-- .... --> |

/pages/About.vue

|---------------------|------------------------------------------------------------------------------| | 1 2 3 4 5 6 | <template> <div> <h2>我是About组件</h2> </div> </template> <!-- .... --> |

嵌套、多级路由 {#嵌套、多级路由}

效果:

使用 children 属性配置子路由 /router/index.js

|------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | // 该文件用于创建路由器 import VueRouter from 'vue-router'; import About from '@/pages/About.vue'; import Home from '@/pages/Home.vue'; import Message from '@/pages/HomePages/Message.vue'; import News from '@/pages/HomePages/News.vue'; // 创建路由器 export default new VueRouter({ routes: [ // 一级路由 { path: '/about', component: About }, { path: '/home', component: Home, children: [ // 二级路由 { // 多级路由不用再写斜杠 path: 'news', component: News }, { path: 'message', component: Message } ], }, ] }); |

修改 Home.vue 组件加上二级路由切换 /pages/Home.vue

|------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 | <template> <div> <h2>我是Home组件</h2> <router-link to="/home/message" active-class="active">Message</router-link> <router-link to="/home/news" active-class="active">News</router-link> <router-view></router-view> </div> </template> <!-- .... --> |

新建二级路由组件 Message.vue 和 News.vue Message.vue 和 News.vue

|------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!-- Message.vue --> <template> <div> <h2>Home的二级路由Message</h2> </div> </template> <!-- .... --> <!-- News.vue --> <template> <div> <h2>Home的二级路由News</h2> </div> </template> <!-- .... --> |

route的属性 {#route的属性}

获取route: 组件中 this.$route,路由守卫中的 tofrom 参数

route上常用属性:

  1. fullPath 该路由的完整路径,带参数
  2. meta 一个对象,允许程序员自由地往里面加内容,可以在配置路由时就设置
  3. name 路由的名字
  4. params params参数
  5. path 路由路径
  6. query 查询字符串参数

路由query传参 {#路由query传参}

通过 url 的 query(查询字符串)参数给子路由组件传参

使用: /pages/HomePages/Message.vue

|------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 | <!-- 模板字符串写法 --> <router-link :to="`/home/message/detail?id=${item.id}&title=${item.title}`">{{ item.title }}</router-link> <!-- 对象写法,推荐 --> <router-link :to="{ path: '/home/message/detail', query: { id: item.id, title: item.title } }"> {{ item.title }}</router-link> |

子路由组件中通过 $route.query.<key> 获取 query 参数 /pages/HomePages/MessageDetail.vue

|-------------|--------------------------------------------------------------------------| | 1 2 | <h3>{{ $route.query.id }}</h3> <h3>{{ $route.query.title }}</h3> |

命名路由 {#命名路由}

给路由起名字,可以简化一些编码工作 /router/index.js

|------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | { // 命名路由 name: 'Message', path: 'message', component: Message, children: [ { name: 'MessageDetail', path: 'detail', component: MessageDetail } ] } |

使用 name 替代 path 配置,也能跳转路径 /pages/HomePages/Message.vue

|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 | <router-link :to="{ name: 'MessageDetail', // path: '/home/message/detail', query: { id: item.id, title: item.title } }">{{ item.title }}</router-link> |

路由params传参 {#路由params传参}

使用 params 传参需要在路由 path 配置中写上 url 参数(占位符) /router/index.js

|---------------------|-------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 | { name: 'MessageDetail', // 写上占位符 path: 'detail/:id/:title', component: MessageDetail } |

**传参:**使用 params 传参,路径只能用 name 写法,不能写 path /pages/HomePages/Message.vue

|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 | <router-link :to="{ name: 'MessageDetail', params: { //传params参数 id: item.id, title: item.title } }">{{ item.title }}</router-link> |

获取参数: $route.params /pages/HomePages/MessageDetail.vue

|-------------|----------------------------------------------------------------------------| | 1 2 | <h3>{{ $route.params.id }}</h3> <h3>{{ $route.params.title }}</h3> |

路由props配置 {#路由props配置}

在路由配置中加上 props: true,该路由组件收到的所有 params 参数 都会以 props 形式呈现 /router/index.js

|------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 | { name: 'MessageDetail', path: 'detail/:id/:title', component: MessageDetail, // 写死数据,一般用不到 // props: {a:'1', b:'2'} // 设置true,该路由组件收到的所有params参数都会以props形式呈现 props: true } |

接收 props /pages/HomePages/MessageDetail.vue

|-------------------|--------------------------------------------------------------------------------------| | 1 2 3 4 5 | export default { name: 'MessageDetail', // 接收props props: ['id', 'title'], } |

props() 写成函数式 ,参数是该路由 $route ,可以自定义返回值,不再局限于之前只能传 params 参数 /router/index.js

|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 | { name: 'MessageDetail', path: 'detail/:id/:title', component: MessageDetail, // 解构赋值从$route中拿出params和query props({params,query}){ return { id: params.id, title: query.title } } } |

replace属性 {#replace属性}

<router-link>replace 属性

作用: 控制路由跳转时,操作浏览器历史记录 的模式为 replace

操作浏览器历史记录有 push (默认) 和 replace 两种模式
(1) push 追加历史记录
(2) replace 替换当前记录,使浏览器不能通过后退返回之前的路径

|-------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 | <router-link to="/home" active-class="active" replace>Home</router-link> <router-link to="/about" active-class="active" replace>About</router-link> |

编程式路由 {#编程式路由}

不使用 <router-link> 标签,通过调用 $router 上的方法,来控制路由的跳转

$router 原型上的 push()replace() 方法分别以pushreplace 两种模式跳转路由,都接收一个配置对象,内容和 to 属性中的一样 /pages/HomePages/Message.vue

|------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <button @click="pushShow(item)">push跳转</button> <button @click="replaceShow(item)">replace跳转</button> <!-- ...... --> <script> // ...... methods: { pushShow(item){ this.$router.push({ name: 'MessageDetail', params: { id: item.id, title: item.title } }) }, replaceShow(item){ this.$router.replace({ name: 'MessageDetail', params: { id: item.id, title: item.title } }) } } // ...... </script> |

$router 的原型上还有其它方法
(1) back() 后退
(2) forward() 前进
(3) go() 前进或后退几个历史记录

在 vue-router 插件的某些版本,使用编程式路由时,相同路径跳转会报错,在路由配置文件中加上这段代码即可 /router/index.js

|---------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // 解决相同路径跳转报错的问题 //先保存一份VueRouter let originPush = VueRouter.prototype.push; let originReplace = VueRouter.prototype.replace; //重写push|replace //第一个参数:往哪里跳(传递哪些参数) VueRouter.prototype.push = function(location,resolve,reject) { if(resolve && reject) { originPush.call(this,location,resolve,reject); } else { originPush.call(this,location,()=>{},()=>{}); } } VueRouter.prototype.replace = function(location,resolve,reject) { if(resolve && reject) { originReplace.call(this,location,resolve,reject); } else { originReplace.call(this,location,()=>{},()=>{}); } } |

缓存路由组件 {#缓存路由组件}

切换路由,旧的路由组件会被销毁,在该组件中的用户输入等操作都会丢失

要想切换路由不销毁旧的组件,可以将 <router-view> 放入 <keep-alive> 标签中,include 属性指定要缓存的组件名(默认全缓存)

**作用:**让不展示的路由组件保持挂载,不被销毁 /pages/Home.vue

|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 | <router-link to="/home/message" active-class="active">Message</router-link> <router-link to="/home/news" active-class="active">News</router-link> <keep-alive include="News-"> <router-view></router-view> </keep-alive> |

两个新钩子 {#两个新钩子}

<keep-alive>能被其缓存路由组件 添加了两个新的生命周期钩子

(1) activated() 路由组件被激活
(2) deactivated() 路由组件失活

作用:activated() 中开启定时器、发AJAX请求等,在 deactivated() 中关闭定时器等

路由守卫 {#路由守卫}

**作用:**对路由进行权限控制

**分类:**全局守卫,独享守卫,组件内守卫

在前端业务中,经常有需要配合后端校验权限后才能打开的页面,如个人中心、订单记录等等,通过路由守卫就能在切换路由前,对权限进行校验,然后控制切不切换页面(放行),或跳转到某一页面(登陆页)

所有守卫本质都是函数 ,除了全局后置守卫 没有第三个参数(next)之外,都有三个参数:
(1) to 要切换的路由对象
(2) from 切换前的路由对象
(3) next 一个函数,无参时切换to的路由,有参时切换到指定路由

三种守卫相互配合实现业务

全局守卫 {#全局守卫}

**全局路由守卫:**监测所有路由的切换,只要切换路由,就会经过全局守卫的业务逻辑

分类:
(1) 全局前置 守卫:在切换路由前 触发的守卫
(2) 全局后置 守卫:在成功切换路由后触发的守卫

配置全局守卫: 在路由配置文件中,通过路由器上的两个方法配置全局守卫
(1) beforeEach(() => {}) 全局前置 守卫
(2) afterEach(() => {}) 全局前置守卫

|---------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ...... */ // 全局前置守卫 router.beforeEach((to, from, next) => { console.log('切换路由前'); console.log(to); console.log(from); next(); }) // 全局后置守卫 router.afterEach((to, from) => { console.log('切换路由后'); console.log(to); console.log(from); // 动态地切换网页标题 if (to.meta.title) { document.title = to.meta.title; } }) |

独享守卫 {#独享守卫}

独享路由守卫: beforeEnter() 只监测某个路由,要切换到该路由,才触发该守卫

**注意:**独享路由守卫没有后置,只在切换到该路由前触发

|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | // 创建路由器 const router = new VueRouter({ routes: [ { name: 'About', path: '/about', component: About, meta: { title: '关于' }, // 独享路由守卫 beforeEnter(to, from, next) { console.log('切换到关于路由前'); console.log(to); console.log(from); // 做一些业务,这里让一秒后再切换 setTimeout(() => { next(); }, 1000); }, }, /* ...... */ ] }); |

组件内守卫 {#组件内守卫}

**组件内路由守卫:**只在某一路由组件实例中生效的守卫,控制进入和离开该组件

分类:
(1) beforeRouteEnter() 通过路由规则 要进入该组件前 触发
(2) beforeRouteLeave() 通过路由规则 要离开该组件前 触发

|------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | export default { name: 'Home-', // 通过路由规则 要进入该组件前 触发 beforeRouteEnter(to, from, next){ console.log('要进入该组件'); console.log(to); console.log(from); next(); }, // 通过路由规则 要离开该组件前 触发 beforeRouteLeave(to, from, next){ console.log('要进入该组件'); console.log(to); console.log(from); next(); } } |

路由器两种工作模式 {#路由器两种工作模式}

路由器有两种工作模式:
(1) hash 模式:url中带 # 号,如 localhost:8080/#/home
(2) history 模式:url中不带 # 号 如 localhost:8080/home

1、hash 模式:

  1. 对于 url 来说,# 号后面的内容都是 hash 值不会包含在 HTTP 请求的路径中,# 号后面的路径只是 vue 路由器工作所需
  2. 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
  3. 兼容性较好,无需后端特地去处理路径问题

2、history 模式:

  1. url 样子较符合常理,也美观
  2. 项目上线后,需要后端去分辨前端路由和后端路由,返回不同的资源,解决 vue 这种单页应用程序切换路由后,刷新页面服务端404的问题,

mode 配置,指定路由器工作模式

|-------------------|------------------------------------------------------------------------------------------| | 1 2 3 4 5 | const router = new VueRouter({ // mode: 'hash', mode: 'history', /* ...... */ }) |

NodeJS-Express 通过中间件 connect-history-api-fallback 自动处理路径问题

Element-UI {#Element-UI}

组件化编码催生出了许多优秀的UI组件库,导入即可使用

Element-UI 为例,vue2 使用 Element,vue3 用 Element Plus

使用组件库更多的是去看其提供的文档

安装: npm i element-ui -S

全部引入:

|------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import Vue from "vue"; import App from "./App.vue"; // 全部引入 import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.config.productionTip = false; // 使用ElementUI插件 Vue.use(ElementUI); new Vue({ el: "#app", render: h => h(App), }) |

按需引入:

安装 babel-plugin-component

修改 babel.config.js

|------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | module.exports = { presets: [ '@vue/cli-plugin-babel/preset', ["@babel/preset-env", { "modules": false }] ], plugins: [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ] ] } |

然后就可以按需引入了

|---------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import Vue from "vue"; import App from "./App.vue"; // 按需引入 import { Button,Row,DatePicker } from 'element-ui'; Vue.config.productionTip = false; // 按需使用 Vue.use(Button); Vue.use(Row); Vue.use(DatePicker); new Vue({ el: "#app", render: h => h(App), }) |

**使用组件:**看文档,cv使用组件标签

|-------------------|----------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 | <el-button type="primary">主要按钮</el-button> <el-date-picker type="date" placeholder="选择日期"> </el-date-picker> |

项目上线 {#项目上线}

打包: npm run build 生成 dist 文件夹

将打包出的文件部署到服务端,交给后端去搞

赞(0)
未经允许不得转载:工具盒子 » Vue笔记[五]-路由