梓潼移动网站建设,网站制作aqq,展台展厅设计,网站建站作业前言
在 Web 前端开发中#xff0c;路由是非常重要的一环#xff0c;但是路由到底是什么呢#xff1f; 从路由的用途上讲 路由是指随着浏览器地址栏的变化#xff0c;展示给用户不同的页面。 从路由的实现原理上讲 路由是URL到函数的映射。它将 URL 和应用程序的不同部分…
前言
在 Web 前端开发中路由是非常重要的一环但是路由到底是什么呢 从路由的用途上讲 路由是指随着浏览器地址栏的变化展示给用户不同的页面。 从路由的实现原理上讲 路由是URL到函数的映射。它将 URL 和应用程序的不同部分映射到特定的处理程序或控制器上。
路由本身也经历了不同的发展阶段 服务端路由 服务端路由也称后端路由。 服务器根据用户访问的 URL 路径返回不同的响应结果。当我们在一个传统的服务端渲染的 web 应用中点击一个链接时浏览器会从服务端获得全新的 HTML然后重新加载整个页面。 对于最简单的静态资源服务器可以认为所有URL的映射函数就是一个文件读取操作。对于动态资源映射函数可能是一个数据库读取操作也可能是进行一些数据处理等等。 好处 安全性好、利于 SEOSearch Engine Optimization搜索引擎优化。是指为了增加网页在搜索引擎自然搜索结果中的收录数量以及提升排序位置而做的优化行为 缺点 加大服务器的压力不利于用户体验代码冗余 正式服务端路由得缺点让客户端路由开始展露头角。 正式服务端路由得缺点让客户端路由开始展露头角。
2. 客户端路由
客户端路由也称前端路由。
当用户通过客户端访问不同的路径时路由的映射函数利用诸如 History API 或是 hashchange 事件这样的浏览器 API 来管理应用当前应该渲染的视图其根本就是操作 DOM 的显示和隐藏。
基于 hash 的实现
早期的前端路由的实现就是基于location.hash来实现的。实现原理也很简单就是监听#后面的内容来发起Ajax请求来进行局部更新而不需要刷新整个页面。
location.hash的值就是URL中#后面的内容。
例如:https://www.happy.com#me中的 location.hash ‘#me’ hash也存在下面几个特性
1.URL中的hash值只是客户端的一种状态也就是说当向服务器发出请求时hash部分不会被发送。
2.hash值的改变都会在浏览器的访问历史中增加一个记录因此我们能通过浏览器的回退前进按钮控制hash 的切换。
3.我们可以使用hashchange事件来监听URL的变化
触发hash变化的方式也有两种
1.通过a标签并设置href属性当用户点击这个标签后URL就会发生变化也就会触发hashchange事件了例如a href#hahhahahha/a2.直接使用js来对location.hash进行赋值从而改变URL 触发hashchange事件例如 location.hash #hahha3.浏览器前进后退改变 URL触发hashchange事件基于 history API 的实现
介绍HTML5 history API
HTML5 history API只包括2个方法history.pushState()和history.replaceState()以及1个事件window.onpopstate。 1.切换历史状态
包括 back() 、forword() 、go(n) 三个方法分别对应浏览器的前进后退跳转操作
history.go(-2) //后退两次 刷新
history.go(2) //前进两次
history.back() //后退 (不刷新)
history.forword() //前进back() 方法可加载历史列表中的前一个 URL(如果存在)。调用该方法的效果等价于点击后退按钮或调用 history.go(-1) forward() 方法可加载历史列表中的下一个 URL。调用该方法的效果等价于点击前进按钮或调用 history.go(1) 2.修改历史状态
包括 pushState() 、replaceState() 两个方法都接收三个参数stateObj 、title、url。它们可以在不刷新页面的情况下操作浏览器的历史记录。
pushState() 新增一个历史记录 replaceState() 替换当前的历史记录 popstate() 事件。用于监听历史记录的变化参数
状态对象(state object)一个JavaScript对象与用 pushState() 方法创建的新历史记录条目关联。无论何时用户导航到新创建的状态会触发popstate 事件并能在事件中使用该对象 标题(title)一般浏览器会忽略传 null 即可 地址(URL)需要新增的历史记录地址浏览器不会去直接加载改地址但后面也可能会去尝试加载该地址。此外需要注意的是传入的URL与当前URL应该是同源的。
window.onpopstate function(event) {alert(location: document.location , state: JSON.stringify(event.state));
};history.pushState({page: 1}, title 1, ?page1);
history.pushState({page: 2}, title 2, ?page2);
history.replaceState({page: 3}, title 3, ?page3);
history.back(); // 弹出 location: http://example.com/example.html?page1, state: {page:1}
history.back(); // 弹出 location: http://example.com/example.html, state: null
history.go(2); // 弹出 location: http://example.com/example.html?page3, state: {page:3}**总结**无论是客户端路由还是服务端路由都有一定的应用场景和适用范围。对于需要提供优秀用户体验和动态交互的 Web 应用客户端路由更为适用而对于需要提供更好的SEO优化和网站性能的网站服务端路由更为适用。但之后的出现了nuxt.js和next.js很大程度上弥补了传统的客户端路由不利于SEO优化的问题。 一、Vue3.0X 中的路由 Vue-router
1 介绍
Vue 很适合用来构建单页面应用。对于大多数此类应用都推荐使用官方支持的Vue Router在单页面应用(Single-page application中客户端的 JavaScript 可以拦截页面的跳转请求动态获取新的数据然后在无需重新加载的情况下更新当前页面。这样通常可以带来更顺滑的用户体验因为这类场景下用户通常会在很长的一段时间中做出多次交互。这类的单页面应用中路由的更新是在客户端执行的。
Vue Router 是 Vue 的官方路由。它与 Vue.js 核心深度集成让用 Vue.js 构建单页应用变得轻而易举。功能包括
嵌套路由映射动态路由选择模块化、基于组件的路由配置路由参数、查询、通配符展示由 Vue.js 的过渡系统提供的过渡效果细致的导航控制自动激活 CSS 类的链接HTML5 history 模式或 hash 模式可定制的滚动行为URL 的正确编码
以下我们来介绍Vue Router的基本使用。
2 Vue Router的使用
2.1 安装 构建前端项目 npm init vuelatest //或者 npm init vitelatest 对于vue3我们推荐使用vue-router 4.x及以上版本。node环境安装如下
# yarn 方式
yarn add vue-router4# npm 方式
npm install vue-router4安装成功后的 package.json 2.2 引入
在我们工程项目中路由文件通常需要单独管理以便于后续的使用以及维护。再此基础下我们引入分为两步
创建统一管理路由入口文件vue项目引入使用路由入口文件
2.2.1 创建路由文件
在与main.ts文件的同级目录下创建router文件夹并添加index.ts文件使用ts若使用js也同理。
文件内容如下
import { createRouter, createWebHistory, RouteRecordRaw } from vue-router;
import Home from ../views/Home.vue;
// 项目其他页面路由推荐使用
import Practice from ../router/practiceFolder/practice;// vue项目自带路由
const routes: ArrayRouteRecordRaw [{path: /,name: Home,component: Home},{path: /about,name: About,component: () import(/* webpackChunkName: about */ ../views/About.vue)}
];const routers [...routes, ...Practice];const router createRouter({history: createWebHistory(process.env.BASE_URL),routes: [...routes, ...Practice]
});export default router;
其中使用RouteRecordRaw声明的对象会被当做路由对象放入到路由对象池里。
createRouter创建路由
createWebHistory代表路由使用 HTML5 模式也是推荐使用的模式
2.2.2 将路由配置文件挂载到 Vue 应用上
# src/main.jsimport { createApp } from vue
import App from ./App.vue
import router from ./router // 默认查找当前路径下的 index.js同 ./router/indexconst app createApp(App)
app.use(router)
app.mount(#app)3 在组件中使用路由
组件中使用路由涉及到**“路由跳转”和“路由出口”**两个概念
router-link
自定义组件用于创建链接。可以使 Vue Router 在不重新加载页面的情况下更改 URL处理 URL 的生成以及编码。
router-view
路由出口用于显示与 url 对应的组件路由映射组件可以放到任何位置。
div idapph1Hello App!/h1p!--使用 router-link 组件进行导航 --!--通过传递 to 来指定链接 --!--router-link 将呈现一个带有正确 href 属性的 a 标签--router-link to/Go to Home/router-linkrouter-link to/aboutGo to About/router-link/p!-- 路由出口 --!-- 路由匹配到的组件将渲染在这里 --router-view/router-view
/div在App.vue中使用router-view组件来渲染要显示的组件在Tabbar组件中使用router-link组件生成链接
4 路由常用API
属性组件
RouterLink 用来渲染一个链接的组件该链接再被点击时会触发导航RouterView 用于显示用户当前所处路由的组件 路由实例函数 createRouter(options) 创建一个可以被 Vue 应用使用的 Router 实例
createRouter({history: createWebHistory(),routes: [{ path: , name: , meta: { }, component: CompA ...}// 其它路由组件配置]// 其它选项配置...
})history 历史记录模式
路由器使用的历史记录模式大多数应该使用 createWebHistory 但这需要正确的配置服务器。
如果不想配置服务器可以使用 createWebHashHistory 来实现基于 hash 的历史记录但这种方式不会被搜索引擎处理SEO 效果较差
createWebHistory(base?) 创建一个 HTML5 历史记录。单页应用最常见的模式。createWebHashHistory(base?) 创建一个 hash 模式的历史记录。无需配置服务器。 createMemoryHistory(base?) 创建一个基于内存的历史主要用于处理服务端渲染。它从一个不存在的特殊位置开始可通过 router.push 或 router.replace 将该位置替换成起始位置。
// 基于 https://example.com/folder
createWebHashHistory() // 给出一个 https://example.com/folder# 的 URL
createWebHashHistory(/folder/) // 给出一个 https://example.com/folder/# 的 URL路由导航守卫
onBeforeRouteLeave(to, from, next) { } 当前位置的组件离开时被触发。onBeforeRouteUpdate(to, from, next) {} 当前位置的组件被更新时触发。 注在组件卸载时所有路由守卫会被移除。 在组件中操作路由的对象
useRouter 返回路由器实例。等价于模板中使用的 $routeruseRoute 返回当前的路由地址。等价于模板中使用 $route。存储了路由跳转时传递的参数信息如params、query 等useLink router 操作函数 push() 程序式地通过将一条记录加入到历史栈中来导航到一个新的 URL resolve() 返回一个路由地址的规范化版本。同时包含一个包含任何现有 base 的 href 属性 replace() 程序式地通过替换历史栈中的当前记录来导航到一个新的 URL addRoute(parentName, route) 添加一个新的路由记录将其作为一个已有路由的子路由。
3 Vue Router 的配置项介绍
我们在使用Vue Router 中的createRouter创建router对象时其为我们提供了很多配置项带完整配置项的示例代码如下
const router createRouter({history: createWebHashHistory(),routes: [],scrollBehavior: () ({ top: 0, left: 0 }),linkActiveClass: active,linkExactActiveClass: exact-active,parseQuery: null,stringifyQuery: null,fallback: true
})上面代码中各个配置项的含义如下
history指定路由的 history 模式目前支持 createWebHistory()和 createWebHashHistory()模式。routes定义路由规则的数组每一个路由规则都是一个对象包含 path、name、component 和 meta 等属性。scrollBehavior指定路由切换时滚动行为的配置函数。该函数返回一个包含 x 和 y 属性的对象表示页面跳转后滚动的位置。linkActiveClass指定激活状态的链接的 class 名称默认为 router-link-active。linkExactActiveClass指定精确匹配的激活状态的链接的 class 名称默认为 router-link-exact-active。parseQuery 和 stringifyQuery用于配置路由的查询参数解析和序列化函数。通常情况下我们不需要额外配置这两个函数因为 Vue Router 已经提供了默认的实现。fallback用于配置是否开启 HTML5 History 模式的回退机制。默认值为 true表示当路由不匹配时将自动回退到历史记录中的上一个路由。
上面的配置项中我们一般只需要配置history和routes两个选项就可以了其它选项了解即可
routes中的配置项介绍
在 Vue Router 中路由规则的配置是通过 routes 属性来实现的。routes 属性中常用的配置如下
name路由规则的名字。可以用于编程式导航和组件内部的路由跳转。path路由的路径可以包含动态参数和正则表达式。例如/user/:id 表示用户页面:id 是一个动态参数。redirect路由的重定向规则。例如{ path: /, redirect: /home } 表示路由根路径的重定向。component路由对应的组件。可以是一个普通的组件类或异步加载的组件。children当前路由的子路由。可以是一个路由规则数组也可以是一个函数动态生成路由规则。meta路由的元信息用于描述路由的一些额外信息。例如路由是否需要登录、权限鉴定等。components路由对应的多个命名视图组件。
路由跳转
通过Vue Router我们可以通过router-link组件的to方法和使用router.push函数以编程方式两种方法导航到路由。
使用 router-link组件
使用router-link组件实现路由跳转我们只需要将菜单按钮使用router-link组件包裹并在上面使用to方法即可进行跳转示例代码如下
divrouter-link to/Home/router-linkrouter-link to/listList/router-linkrouter-link to/aboutAbout/router-link
/div使用router.push函数
使用router.push函数以编程方式实现路由跳转我们只需要在普通按钮上绑定click事件并在事件中调用router.push()方法即可实现跳转示例代码如下:
templatedivrouter-link to/Home/router-linkrouter-link to/listList/router-linkrouter-link to/aboutAbout/router-linkbutton clickgotoAbout 关于 /button/div/template
script setup
import { useRouter } from vue-router
const router useRouter()
const gotoAbout () {router.push(/about)
}
/script使用 router.push 方法会向 history 栈添加一个新的记录所以当用户点击浏览器后退按钮时会回到之前的 URL。
事实上当我们点击 router-link 时Vue Router 内部会调用这个方法所以点击 router-link :to... 相当于调用 router.push(...)
router.push()方法中的参数可以是一个字符串路径或者一个描述地址的对象。
// 字符串路径
router.push(/users/eduardo)// 带有路径的对象
router.push({ path: /users/eduardo })// 命名的路由并加上参数让路由建立 url
router.push({ name: user, params: { username: eduardo } })// 带查询参数结果是 /register?planprivate
router.push({ path: /register, query: { plan: private } })// 带 hash结果是 /about#team
router.push({ path: /about, hash: #team })路由传参
在Vue Router中可以通过以下方式进行路由传参和获取参数
通过路由路径传递参数在路由配置中使用动态路由匹配Dynamic Route Matching例如
const routes [{path: /detail/:id,name: Detail,component: Detail}]在路由路径中使用冒号表示参数参数值会被放入route.params对象中。我们可以通过调用route.params获取参数如访问地址为/detail/123则我们可以通过route.params.id获取值为123。
2 通过query参数传递参数在路由跳转时使用query参数例如
// 在组件中跳转
router.push({path: /detail,query: { id: 123 }
})// 在模板中跳转
router-link to/detail?id123Detail/router-link在路由中使用query参数时参数值会被放入route.query对象中。我们可以通过route.query获取参数。例如访问地址为/detail?id123则我们可以通过route.query.id获取值为123。
3 在路由配置中通过props选项传递参数。例如
const routes [{path: /detail/:id,name: Detail,component: Detail,props: { id: 123 }}]在组件中可以直接使用props接收参数
4 在路由配置中通过meta选项传递参数。例如
const routes [{path: /detail/:id,name: Detail,component: Detail,meta: { id: 123 }}]在组件中可以通过route.meta获取参数
动态路由
动态路由是指将一个路由的一部分作为参数来构建的路由。例如如果我们要为每个用户创建一个单独的页面我们可以使用动态路由创建一个路径为/users/:userId的路由其中:userId是一个参数。
动态路由在定义路由时使用冒号:来表示参数。定义动态路由需要使用path方式定义。例如要定义一个动态路由我们可以这样写
{path: /users/:userId,name: user,component: User
}在上面的代码中路径中的:userId表示一个参数它可以从路由对象的params属性中获取。在组件中可以这样读取userId
console.log(route.params.userId)在使用动态路由时Vue Router还支持使用可选的参数和正则表达式来定义路由。例如可以这样定义一个包含可选参数的动态路由
{path: /users/:userId/:postId?,name: post,component: Post
}在上面的代码中路径中的postId参数是可选的我们在它后面加一个问号代表可选参数。现在如果路径是/users/123那么postId将是undefined如果路径是/users/123/456那么postId将是456。
嵌套路由
嵌套路由允许我们在一个父级路由下嵌套多个子路由从而形成更加复杂的页面结构。
要定义嵌套路由我们可以在父级路由的routes数组中定义一个子路由对象数组每个子路由对象都包含一个path和一个component属性表示当前子路由的访问路径和对应的组件。同时我们还可以在子路由对象中定义子路由的子路由从而形成嵌套的路由结构。
我们使用配置项children表示路由的嵌套关系如下示例代码
const routes [{path: /,component: Home,children: [{path: about,component: About},{path: contact,component: Contact}]}]在上面的代码中我们定义了一个名为Home的组件作为父级路由的组件并在children数组中定义了两个子路由About和Contact。这样当用户访问/about或/contact时Vue Router 就会渲染对应的子组件并将其嵌套在Home组件内。
命名路由
命名路由可以为路由设置一个名称以便在代码中进行引用和跳转。使用命名路由可以让代码更加清晰易懂尤其是在需要跳转到具有动态参数的路由时。
要定义命名路由我们可以在路由对象中使用name属性来指定路由的名称例如
const routes [{path: /,name: home,component: Home},{path: /about,name: about,component: About},{path: /user/:id,name: user,component: User}]在上面的代码中我们为三个路由分别指定了名称home、about和user。然后在代码中我们可以通过这些名称来生成对应的路由链接或路由跳转例如
router-link :to{name: home}Home/router-linkrouter-link :to{name: about}About/router-linkrouter-link :to{name: user, params: {id: 123}}User 123/router-linkrouter.push({name: home})router.push({name: user, params: {id: 456}})在上面的代码中我们分别使用了router-link组件和router.push()方法来跳转到具有命名路由的路由。其中使用params属性可以动态指定路由中的参数。
命名路由在需要动态传递参数的情况下使用非常方便。
一文详解:Vue3中使用Vue Router_router vue3_九仞山的博客-CSDN博客
路由守卫
路由守卫是一种函数在路由的各个阶段被调用可以用于拦截路由的访问或对路由进行一些操作。我们可以使用路由守卫来控制路由的跳转和访问权限。
在路由守卫中我们通常会用到三个参数to、from和next。
to表示即将要跳转的目标路由对象包含路由的路径、参数和查询字符串等信息。from表示当前路由对象即正在离开的路由对象。next是一个函数用于进行路由控制和跳转。当调用next函数时路由会继续向下执行。我们可以通过next函数来控制路由的行为例如渲染组件、跳转路由、取消操作等。
几种使用next函数的情况 next(): 表示继续执行下一个路由守卫。 next(false): 表示取消当前的路由跳转。 next(/path): 表示跳转到指定的路由路径。 next(error): 表示在路由跳转过程中发生了错误例如权限不足等。
需要注意的是在使用路由守卫时我们需要显式地调用next函数来控制路由的跳转和功能否则路由不会继续向下执行。在不同的守卫中next函数的行为和功能也会有所不同需要根据具体的场景进行调用。
Vue Router中的路由守卫分为全局路由守卫和路由独享守卫
全局路由守卫
全局路由守卫是在整个应用中都生效的守卫可以用于拦截所有的路由操作。在Vue Router4中全局守卫有三个beforeEach、beforeResolve和afterEach。
beforeEach: 在路由跳转之前执行可以用于进行全局的访问控制或重定向跳转等操作。beforeResolve: 在路由跳转完成前执行可以用于等待异步路由组件加载完成或在路由跳转前进行一些操作。afterEach: 在路由跳转完成后执行可以用于对页面进行一些操作例如监测页面埋点或修改页面标题等。
一个验证用户是否登录的路由守卫示例代码如下
router.beforeEach((to, from, next) {if (to.name ! Login !isAuthenticated) next({ name: Login })else next()
})上面代码中如果用户没有登录则页面跳转到Login页面如果已经登录则执行next()跳转
路由独享守卫
路由独享守卫仅对当前路由生效可以用于限制或增强某个路由的访问权限。在Vue Router4中路由独享守卫有两个beforeEnter和leaveGuard。 beforeEnter: 在进入当前路由之前执行可以用于增强当前路由的访问权限或进行相关操作。 leaveGuard: 在离开当前路由之前执行可以用于给用户提示或进行相关操作。
使用路由守卫时我们可以在createRouter函数中进行注册例如
const routes[{path: /,component: Home},{path: /about,component: About,beforeEnter: (to, from, next) {// 进行路由访问控制或相关操作}}]路由懒加载
路由懒加载是一种将路由组件按需异步加载的方式只有当路由对应的组件需要使用时才会动态地加载该组件对应的代码。使用路由懒加载可以优化应用程序的性能
在Vue Router中使用路由懒加载我们可以通过使用import()和动态import()两种方式来实现
使用import()方式实现懒加载
const Home () import(./views/Home.vue)
const About () import(./views/About.vue)
const routes [{path: /,component: Home},{path: /about,component: About}]
const router createRouter({history: createWebHistory(),routes
})使用动态import()方式实现懒加载 箭头函数
const routes [{path: /,component: () import(./views/Home.vue)},{path: /about,component: () import(./views/About.vue)}
]
const router createRouter({history: createWebHashHistory(),routes
})使用Vue Router的注意事项
动态参数不能有斜杆当使用动态参数时请注意URL不能和动态参数相同。导航流程:路由类似于栈每次路由的跳转都会被历史纪录中的历史记录所记录。如果你跳转到相同的路由那么历史记录中的最后几次都会被忽略。默认情况下新跳转的路由不会触发路由更新流程你需要显式地使用router.push或者router.replace方法来更新到当前路由。导航被取消如果你在beforeRouteLeave或beforeRouteUpdate守卫中执行了异步操作则必须确保该异步操作已经完成并调用了next(true)以确保导航可以进行。 补充知识
浅析 useRoute() 、useRouter() useRoute()、useRouter()本质是两个函数是用于获取路由相关信息。useRoute()用于返回当前路由信息对象用于接收路由参数。useRouter()用于返回当前路由实例常用于实现路由跳转。使用方法先引入且需要调用两个函数才可以得到相关信息。 一、useRoute() 打印useRoute()可以看到返回的是对象里面包含matched、meta、name、params、query、path等路由参数信息。 fullPath显示当前路由路径包含子路由如 value: /acl/user
matched值为数组其数组的长度是路由层级数组内容包含二级路由和完整路由如下图 关于matched需要注意在面包屑功能中需要用到matched提供的数组信息进行渲染 meta获取当前路由元信息
name当前路由名称
params、query当前路由参数
path当前路由完整路径
二、useRouter() useRouter()对象中包含了很多路由跳转的方法replace()、push()、back()、go()、addRoute()、hasRoute()、removeRoute()等常用的路由方法 Vue Router的基本概念
路由器Vue Router 提供了一个路由器用于管理应用程序中的路由。Vue Router 实例化一个 Vue Router 对象注册路由规则并以它为中心连接其他组件。
路由路由是分发到不同组件的 URL 地址。在 Vue Router 中路由通常是由 path 规则和相应的组件定义的。当浏览器的 URL 匹配到路由的 path 后相应的组件将会被加载到页面中。路由的信息可以从 route 对象中获取。
路由规则路由规则是由 path、component、name、meta、props 等属性组成的。其中path 表示 URL 的路径component 表示要渲染的组件name 表示路由名称meta 表示路由的元数据props 表示路由 props 数据。路由规则可以注册到 Vue Router 中。
导航守卫导航守卫是在路由跳转时执行的钩子函数用于控制路由的访问权限、处理路由跳转前后的逻辑等。在 Vue Router 中对于选项式 API常用的导航守卫有 beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave 等对于使用组合 API 和 setup 函数来编写组件的可以通过 onBeforeRouteUpdate 和 onBeforeRouteLeave 分别添加 update 和 leave 守卫。 一文详解:Vue3中使用Vue Router_router vue3_九仞山的博客-CSDN博客
【Vue3 生态】Vue Router 路由知识概览_vue3路由_MagnumHou的博客-CSDN博客
什么是路由?_chenwan8029的博客-CSDN博客
HTML5 history API创造更好的浏览体验_清蓝哈哈的博客-CSDN博客
浅析 useRoute() 、useRouter()_useroute和userouter的区别_tomtomgogo的博客-CSDN博客