当前位置: 首页 > news >正文

【vue(一))路由】

路由

  • 一、前端路由的理解
    • 1.SPA单页面应用
    • 2.路由
  • 二、路由实现本质
    • 1.浏览器的两种路由模式
      • (1)hash模式
      • (2)history模式
    • 2.避开浏览器默认行为
  • 三、几种跳转的对比
    • 1.location.href = '/url'
    • 2. history.pushState('/url')
    • 3.router.push('/url') -- Vue Router
    • 4.对比
  • 四、创建路由
    • 1.安装 Vue Router
    • 2.创建路由配置文件
    • 3.在main.js中注册路由
    • 4.在App.vue中显示路由组件
  • 五、`$route`和`$router` 的区别
  • 六、动态路由匹配
  • 七、嵌套路由,命名路由,路由重定向
  • 八、路由跳转的两种方式
  • 九、路由传递参数写法
    • 1.params参数
    • 2.query参数
    • 3.params和query传参的三种写法
    • 4.props传递
  • 十、路由元信息
  • 十一、路由导航守卫
    • 1.全局前置守卫
  • 十二、路由懒加载
    • 1.使用箭头函数+import动态加载
    • 2.使用箭头函数+require动态加载
    • 3.使用webpack的require.ensure技术

一、前端路由的理解

1.SPA单页面应用

(1)在前端技术早期,一个url对应一个页面。

eg:早期博客网站(传统的多页应用MPA

  • 点击首页的一篇文章
  • 浏览器向服务器发送请求
  • 服务器收到请求后,生成一个完整的HTML页面
  • 服务器把这个完整的HTML文件返回给浏览器
  • 浏览器完全刷新页面,丢掉原来的首页内容,加载新的HTML页面

(2)ajax出现,允许在不刷新页面的情况下发请求,随之出现SPA

  • 在SPA初期,在内容切换前后,页面的URL是一样的。
  • 问题一:SPA不会记住你的操作
    • 在博客网站点击帖子内容,但是URL并没有变,点击刷新,又回到首页,刚才的帖子页
  • 问题二:SEO 不够友好
    • 早期爬虫抓取网页内容,但是并不执行js,所以当它们访问SPA时,只能看到那个几乎是空白的HTML文件,而无法获取任何通过JavaScript动态加载的内容。

(3)因此路由出现了

路由的作用就是将浏览器的URL和用户看到的内容绑定起来。当用户浏览不同页面时,URL随之更新,但不需要从服务器重新加载。

2.路由

路由要解决的两个问题

  • (1)问题一
    • 浏览器默认行为:看到URL改变就会向服务器发请求。所以必须避开这种行为。
  • (2)问题二:
    • 感知URL变化,实现"前进/后退":让用户看到URL变化,但不刷新页面,同时记录历史

二、路由实现本质

1.浏览器的两种路由模式

模式描述特性
hash模式依赖 URL 的 哈希部分(# 后面的内容。当哈希值发生变化,触发hashchange事件。前端通过监听该事件,根据哈希值动态渲染页面内容。兼容所有现代浏览器哈希部分不会被发送到服务器url不美观无法利用浏览器的前进、后退功能进行复杂的路由操作
history模式基于 HTML5 History API功能强大需要服务器支持

(1)hash模式

hash模式的主要原理就是onhashchange()事件:

  • 页面hash值发生改变,无需向后端发起请求,window就可以监听事件的改变
window.onhashchange = function(event){console.log(event.oldURL, event.newURL);let hash = location.hash.slice(1);//location.hash返回当前 URL 中以 # 开头的 hash 部分//slice去掉#
}

(2)history模式

history 路由模式的实现,基于 HTML5 提供的 History 全局对象,它的方法有:

-在这里插入图片描述

  • history模式需要后台配置支持。如果后台没有正确配置,访问时会返回404
  • 如果想要切换到history模式,就要进行以下配置(后端也要进行配置)
const router = new VueRouter({mode: 'history',routes: [...]
})

2.避开浏览器默认行为

  • 不使用 <a href> 进行跳转,而是用 JS 控制
  • 用 history.pushState() 替代直接跳转 → 不触发请求
  • 监听页面的 popstate 事件 → 捕捉“前进/后退”

三、几种跳转的对比

1.location.href = ‘/url’

(1)刷新页面,破坏SPA体验
(2)等同于点击 <a href="/about">,是传统的多页跳转方式

2. history.pushState(‘/url’)

(1)无刷新页面
(2)浏览器提供的原生 API,属于 HTML5 History API 的一部分。
(3)只负责改变URL并更新浏览器的历史记录栈,不会自动处理视图更新

3.router.push(‘/url’) – Vue Router

(1)无刷新页面
(2)不仅可以改变 URL,还能够基于 URL 自动匹配并渲染相应的组件
(3)提供了诸如导航守卫、懒加载、参数解析等额外功能

4.对比

在这里插入图片描述

四、创建路由

1.安装 Vue Router

//vue2推荐@3.x
//vue3推荐@4.x
npm install vue-router@4

2.创建路由配置文件

  • 可以把路由规则放在routers.js文件,到时候在这引入就行
  • 路由插件
    • 1.全局注册RouterView 和 RouterLink 组件
    • 2.添加全局 $router 和 $route 属性
    • 3.启用 useRouter() 和 useRoute() 组合式函数
    • 4.触发路由器解析初始路由。
// src/router/index.js
import Vue from 'vue';
import VueRouter from 'vue-router';// 1. 安装 VueRouter 插件(关键!)
Vue.use(VueRouter);// 2. 引入需要路由控制的组件
import Home from '@/views/Home.vue';
import About from '@/views/About.vue';
import User from '@/views/User.vue';// 3. 定义路由规则
const routes = [{path: '/',name: 'Home',component: Home},{path: '/about',name: 'About',component: About},{path: '/user/:id', // 动态路由参数name: 'User',component: User,props: true // 将参数作为 props 传入组件},{path: '/login',redirect: '/auth' // 重定向},{path: '/auth',component: () => import('@/views/Auth.vue') // 懒加载(推荐)},{path: '*',component: () => import('@/views/NotFound.vue') // 404 页面}
];// 4. 创建路由实例
const router = new VueRouter({mode: 'history', // 可选:'hash' 或 'history'base: process.env.BASE_URL,routes  // 相当于 routes: routes
});// 5. 导出路由实例
export default router;

3.在main.js中注册路由

// src/main.js
import Vue from 'vue';
import App from './App.vue';// ✅ 引入路由
import router from '@/router';// ✅ 引入并使用 Vuex(可选)
import store from '@/store';new Vue({render: (h) => h(App),// ✅ 注册路由:让所有组件都能访问 $route 和 $routerrouter,// ✅ 注册 store(如果使用 Vuex)store}).$mount('#app');

4.在App.vue中显示路由组件

使用 <router-view> 显示组件内容
在这里插入图片描述

五、$route$router 的区别

注册完路由后,不管是路由组件还是非路由组件身上都有这两个属性

项目本质属性
$route当前路由的信息对象path,params,hash,query,fullPath,matched,name 等路由信息参数
$router路由实例对象路由的跳转方法,钩子函数

六、动态路由匹配

  • 在定义路由时,允许某些部分是动态变化的
  • 大多情况下,我们需要将给定匹配模式的路由映射到同一个组件,例如user组件的渲染会有用户id的不同
import User from './User.vue'// 这些都会传递给 `createRouter`
const routes = [// 动态字段以冒号开始,称之为路径参数{ path: '/users/:id', component: User },
]
  • 当一个路由被匹配时,它的 params 的值将在每个组件中以 route.params 的形式暴露出来
  • 通过更新 User 的模板来呈现当前的用户 ID
<template><div><!-- 当前路由可以通过 $route 在模板中访问 -->User {{ $route.params.id }}</div>
</template>

七、嵌套路由,命名路由,路由重定向

const routes = [// 重定向:根路径跳转到首页{ path: '/', redirect: { name: 'home' } },// 命名路由 + 嵌套路由{path: '/admin',name: 'admin',component: AdminLayout,children: [{path: 'user',name: 'admin-user',component: UserList,children: [{path: 'add',name: 'admin-user-add',component: UserAdd}]}]}
]
<!-- 使用命名路由跳转 -->
<router-link :to="{ name: 'admin-user-add' }">新增用户</router-link>

八、路由跳转的两种方式

  • 声明式导航 router-link
  • 编程式导航 push | replace
  • 声明式导航能做的,编程式导航都能做;但是编程式导航除了能进行路由跳转,还可以做其他业务逻辑。
    在这里插入图片描述

九、路由传递参数写法

1.params参数

  • 路径参数(是URL的一部分)
  • 在配置路由时需要占位
  • 给params后面加上代表参数可传可不传
  • 携带params参数时,使用to的对象写法只能用name配置!,不能用path配置

2.query参数

  • 不属于路径的一部分,
  • /home?k=v&k=v,配置路由的时候不需要占位

3.params和query传参的三种写法

使用router.push()
这里我感觉少用<router-link :to=''>传参吧,可以用它进行单纯的路由跳转?反正传参emmmm反正我有点绕。等用到了再说吧。

goSearch() {//搜索按钮的回调函数,需要向search路由跳转并传参给search//第一种传参方式:字符串// this.$router.push('/search/' + this.keyword + '?k=' + this.keyword.toUpperCase());//第二种传参方式:模板字符串// this.$router.push(`/search/${this.keyword}?k=${this.keyword.toUpperCase()}`);//第三种传参方式:对象写法this.$router.push({// path: '/search',  和params一起时不能用path只能namename: 'sousuo',params: { keyword: this.keyword },query: { k: this.keyword.toUpperCase() },})
}

4.props传递

props可以写成布尔值,对象模式,函数模式

    {name: 'search',  // 是当前路由的标识名称path: '/search/:keyword?',component: Search,// 将params参数和query参数映射成属性传入路由组件//写法一:布尔值,只能传递prams参数// props:true//写法二:对象写法-->死数据(额外给路由组件传递一些props)//props:{a:1,b:2}//写法三:函数 可以传params和query参数props: ($route)=> {return { keyword3: $route.params.keyword, keyword4: $route.query.keyword2 }},
//子组件接收
prop:[ 'keyword3','keyword4']

十、路由元信息

  • 你可能希望将任意信息附加到路由上,如过渡名称谁可以访问路由等
  • 这些事情可以通过接收属性对象的meta属性来实现,并且它可以在路由地址和导航守卫上都被访问到
  • 暂时没用到多少,后面用多了再说

一个例子:

//例如在home首页,我希望显示footer组件,但是在其他页面不想显示footer组件,我就可以写meta元信息{path: '/',component: () => import('@/pages/Home'),meta: {isHideFooter: true}},
    <!-- 利用路由元信息解决当前问题好处:一行代码就可以解决 --><Footer v-show="$route.meta.isHideFooter" />

十一、路由导航守卫

  • 全局前置/钩子:beforeEach、beforeResolve、afterEach
  • 路由独享的守卫:beforeEnter
  • 组件内的守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
  • 暂时只用过全局前置守卫来进行页面跳转守卫

1.全局前置守卫

// GOOD
router.beforeEach((to, from, next) => {//to:获取到要跳转到的路由信息//from:获取到从哪个路由跳转过来来的信息// next();直接调用,代表直接放行next()
})

十二、路由懒加载

非懒加载

import List from '@/components/list.vue'
const router = new VueRouter({routes: [{ path: '/list', component: List }]
})

1.使用箭头函数+import动态加载

方案一(常用):

const List = () => import('@/components/list.vue')
const router = new VueRouter({routes: [{ path: '/list', component: List }]
})

2.使用箭头函数+require动态加载

const router = new Router({routes: [{path: '/list',component: resolve => require(['@/components/list'], resolve)}]
})

3.使用webpack的require.ensure技术

// r就是resolve
const List = r => require.ensure([], () => r(require('@/components/list')), 'list');
// 路由也是正常的写法  这种是官方推荐的写的 按模块划分懒加载 
const router = new Router({routes: [{path: '/list',component: List,name: 'list'}]
}))
http://www.lryc.cn/news/617986.html

相关文章:

  • 爬虫与数据分析相结合案例总结
  • Vue2篇——第二章 Vue从指令修饰符到侦听器的全面解析(重点)
  • 亚马逊广告进阶指南:如何快速打开新品的流量
  • Python笔记之`getattr`和`hasattr`用法详解
  • Docker中ES安装分词器
  • 【11-计算机视觉介绍】
  • 【代码随想录day 17】 力扣 654.最大二叉树
  • LeetCode151~188题解
  • Apache RocketMQ:消息可靠性、顺序性与幂等处理的全面实践
  • Docker 详解(保姆级安装+配置+使用教程)
  • MySQL高可用改造之数据库开发规范(大事务与数据一致性篇)
  • C++方向知识汇总(三)
  • Git 常用命令总结
  • 泰国文字识别技术:从精准识别字符向深度理解语义的方向不断进化
  • 日本VPS内存溢出了如何优化
  • 数据变而界面僵:Vue/React/Angular渲染失效解析与修复指南
  • 稠密检索:基于神经嵌入的高效语义搜索范式
  • 【LeetCode 热题 100】(七)链表
  • 数据结构——树(02构造二叉树,代码练习)
  • 【网络基础】深入理解 TCP/IP 协议体系
  • 无人机航拍数据集|第11期 无人机人员行为目标检测YOLO数据集1868张yolov11/yolov8/yolov5可训练
  • libwebsockets 服务端获取过代理的真实连接IP
  • [4.2-1] NCCL新版本的register如何实现的?
  • AI(领域)应用落地技术决策指南:从双路径架构到系统性实施
  • Oracle 23AI 稳定执行计划:SQL Profile
  • 训练苹果风格Emoji生成模型的技术方案
  • Docker-09.Docker基础-Dockerfile语法
  • 数据上云有什么好处?企业数据如何上云?
  • Flutter Provider 状态管理全面解析与实战应用:从入门到精通
  • priority_queue(优先级队列)和仿函数