Vue前端路由
路由的基本概念与原理
- 学习目标
= 能够说出路由的概念与原理- 能够说出Vue-router的基本使用步骤
- 能够说出Vue-router的嵌套路由用法
- 能够说出Vue-router动态路由匹配用法
- 能够说出Vue-router命名路由用法
- 能够说出Vue-router编程式导航用法
- 能够基于路由的方式实现业务功能
路由的基本概念与原理
-
路由
- 路由的本质就是一种对应关系,
- 比如说我们在url地址中输入我们要访问的url地址之后,浏览器要去请求这个url地址对应的资源。
- url地址和真实的资源之间就有一种对应的关系,就是路由。
-
路由的分类
- 后端路由
- 概念:根据不同的用户URL请求,返回不同的内容
- 本质:URL请求地址与服务器资源之间的对应关系
- 是由服务器端进行实现,并完成资源的分发
- 性能相对前端路由来说较低
- 前端路由
- 概念:根据不同的用户事件,显示不同的页面内容
- 本质:用户事件与事件处理函数之间的对应关系
- 是依靠hash值(锚链接)的变化进行实现
- 后端路由
-
SPA
- 后端渲染(存在性能问题)
- Ajax前端渲染(前端渲染提高性能),但是不支持浏览器的前进后退操作
- SPA单页面应用程序
- 整个网站只有一个页面
- 内容的变化通过Ajax局部更新实现
- 同时支持浏览器地址栏的前进与后退操作
- SPA实现原理之一:基于URL地址的hash(hash的变化会导致浏览器记录访问历史的变化,但是hash的变化不会触发新的URL请求)
- 在实现SPA过程中,最核心的技术点就是前端路由
-
前端路由的基本概念
- 根据不同的事件来显示不同的页面内容,即事件与事件处理函数之间的对应关系
前端路由主要做的事情就是监听事件并分发执行事件处理函数
- 根据不同的事件来显示不同的页面内容,即事件与事件处理函数之间的对应关系
-
前端路由的初体验
- 前端路由是基于hash值的变化进行实现的
- 比如点击页面中的菜单或者按钮改变URL的hash值
- 根据hash值的变化来控制组件的切换
- 核心实现依靠一个事件,即监听hash值变化的事件
-
核心思路
- 在页面中有一个vue实例对象,vue实例对象中有四个组件,分别是tab栏切换需要显示的组件内容,在页面中有四个超链接
- 当我们点击这些超链接的时候,就会改变url地址中的hash值
- 当hash值被改变时,就会触发onhashchange事件
- 在触发onhashchange事件的时候
- 我们根据hash值来让不同的组件进行显示
window.onhashchange = function(){
//location.hash可以获取到最新的hash值
location.hash
}
- 前端路由实现tab栏切换
<section id='app'>
<a href="#/zhuye">主页</a>
<a href="#/keji">科技</a>
<a href="#/caijing">财经</a>
<a href="#/yule">娱乐</a>
<component :is="comName"></component>
</section>
const zhuye = {
template: '<h1>主页信息</h1>'
}
const keji = {
template: '<h1>科技信息</h1>'
}
const caijing = {
template: '<h1>财经信息</h1>'
}
const yule = {
template: '<h1>娱乐信息</h1>'
}
const vm = new Vue({
el: '#app',
data: {
comName: 'zhuye'
},
components: {
zhuye,
keji,
caijing,
yule
}
})
window.onhashchange = function(){
switch(location.hash.slice(1)){
case '/zhuye':
vm.comName = 'zhuye';
break;
case '/keji':
vm.comName = 'keji';
break;
case '/caijing':
vm.comName = 'caijing';
break;
case '/yule':
vm.comName = 'yule';
break;
}
}
Vue Router 基本使用
-
Vue Router
概述- 它和Vue.js的核心深度集成,可以非常方便的用于SPA应用程序的开发
- 它是一个Vue.js官方提供的路由管理器。是一个功能更加强大的前端路由器,推荐使用
- Vue Router和Vue.js非常契合,可以一起方便的实现SPA(single page web application,单页应用程序)应用程序的开发
- Vue Router依赖于Vue,所以需要先引入Vue,再引入Vue Router
-
Vue Router
特性- 支持H5历史模式或者hash模式
- 支持嵌套路由
- 支持路由参数
- 支持编程式路由
- 支持命名路由
- 支持路由导航守卫
- 支持路由过渡动画特效
- 支持路由懒加载
- 支持路由滚动行为
-
Vue Router
基本使用- 引入相关的库文件
<script src='./js/vue.js'></script>
<script src='vue-router.js'></script>
- 添加路由链接
<router-link>
是路由中提供的标签,默认会被渲染为a标签- to属性默认被渲染为href属性
- to属性的值会被渲染为#开头的hash地址
<router-link to="/user">User</router-link>
<router-link to="/login">Login</router-link>
- 添加路由填充位(路由占位符)
- 将来通过路由规则匹配到的组件,将会被渲染到
router-view
所在的位置 <router-view></router-view>
- 将来通过路由规则匹配到的组件,将会被渲染到
- 定义路由组件
const User = { template:"<div>This is User</div>" }
const Login = { template:"<div>This is Login</div>" }
- 配置路由规则并创建路由实例
const router = new VueRouter({})
routes
是路由规则数组- 每个路由规则都是一个配置对象,其中至少包含
path
和component
两个属性 path
表示当前路由规则匹配的hash
地址component
表示当前路由规则对应要展示的组件
- 把路由挂载到Vue根实例中
- ES6中,若属性名和属性值相同,可简写
- 引入相关的库文件
<section id='app'>
<router-link to="/user">User</router-link>
<router-link to="/login">Login</router-link>
<router-view></router-view>
</section>
const user = {
template: "<div>This is User组件</div>"
}
const login = {
template:"<div>This is Login组件</div>"
}
const router = new VueRouter({
routes: [
{path: '/user', component: user},
{path: '/login', component: login},
]
})
const vm = new Vue({
el: '#app',
router
})
Vue Router 重定向
- 路由重定向
- 概念:用户在访问地址A的时候,强制用户跳转到地址C,从而展示特定的组件页面
- 通过路由规则
redirect
属性,指定一个新的路由地址,可以很方便地设置路由的重定向 - 可以通过路由重定向为页面设置默认展示的组件
- 在路由规则中添加一条路由规则即可
{path: '/', redirect:"/user"}
var router = new VueRouter({
//routes是路由规则数组
routes: [
//path设置为/表示页面最初始的地址 / ,redirect表示要被重定向的新地址,设置为一个路由即可
{ path:"/",redirect:"/user"},
{ path: "/user", component: User },
{ path: "/login", component: Login }
]
})
Vue Router 嵌套路由
-
嵌套路由的概念
- 当我们进行路由的时候显示的组件中还有新的子级路由链接以及内容
- 嵌套路由最关键的代码在于理解子级路由的概念
-
嵌套路由功能分析
- 点击父级路由链接显示模板内容
- 模板内容中又有子级路由链接
- 点击子级路由链接显示子级模板内容
-
嵌套路由配置
- 父级路由通过children属性配置子级路由
const router = new VueRouter({
routes: [{
path: '/user', component: user
},{
path: '/register',
component: register,
children: [{
path: '/register/table1', component: tab1
},{
path: '/register/table2', component: tab2
}]
}]
})
<section id='app'>
<router-link to="/user">User</router-link>
<router-link to="/register">register</router-link>
<router-view></router-view>
</section>
const user = {
template: "<div>This is User组件</div>"
}
const register = {
template: `<div>
<h1>Register组件</h1>
<hr/>
<!-- 子路由链接 -->
<router-link to='/register/tab1'>tab1</router-link>
<router-link to='/register/tab2'>tab2</router-link>
<router-view></router-view>
</div>`
}
const tab1 = {
template: "<h3>This is tab1 组件</h3>"
}
const tab2 = {
template: "<h3>This is tab2 组件</h3>"
}
const router = new VueRouter({
routes: [
{path: '/', redirect:"/user"},
{path: '/user', component: user},
{
path: '/register',
component: register,
children: [{
path: '/register/tab1', component: tab1
},{
path: '/register/tab2', component: tab2
}]
},
]
})
const vm = new Vue({
el: '#app',
router
})
动态路由匹配
-
概念:
- 动态路由就是可以接收参数数据的路由形式,路由地址的一部分是会发生变化的
- 通过
$route.params
接收动态路由传递的参数
-
应用场景
- 通过动态路由参数的模式进行路由匹配
const router = new VueRouter({
router: [
{path: '/user/:id', component: user}
]
})
const user = {
template: '<div>user {{ $route.params.id }}</div>'
}
<section id='app'>
<router-link to="/user/1">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link to="/login">Login</router-link>
<router-view></router-view>
</section>
const user = {
template: "<div>{{ $route.params.id }}</div>"
}
const login = {
template:"<div>This is Login组件</div>"
}
const router = new VueRouter({
routes: [
{path: '/', redirect:"/user"},
{path: '/user/:id', component: user},
{path: '/login', component: login},
]
})
const vm = new Vue({
el: '#app',
router
})
路由组件传递参数
-
路由组件传递参数
$route
与对应路由形成高度耦合,不够灵活,所以可以使用props
将组件和路由解耦props
的值为布尔类型props
的值为对象类型props
的值为函数类型
-
props
的值为布尔类型 核心代码
const router = new VueRouter({
routes: [
// 如果props被设置为true,route.params将会被设置为组件属性
{path: '/user/:id', component: user, props: true}
]
})
const user = {
props: ['id'], // 使用props接收路由参数
template: '<div>用户ID:{{ id }}</div>' // 使用路由参数
}
props
的值为对象类型 核心代码id
访问不到了
const router = new VueRouter({
routes: [
// 如果props被是一个对象,它会被按原样设置为组件属性
{path: '/user/:id', component: user, props: {uname: 'tom', age: 12}}
]
})
const user = {
props: ['uname', 'age'], // 使用props接收路由参数
template: '<div>用户信息:{{ uname+ '-----'+ age }}</div>' // 使用路由参数
}
props
的值为函数类型 核心代码
const router = new VueRouter({
routes: [
// 如果props被是一个函数,则这个函数接收route对象为自己的形参
{
path: '/user/:id',
component: user,
props: route => {
{
uname: 'jerry',
age: '20',
id: route.params.id
}
}
}
]
})
const user = {
props: ['uname', 'age', 'id'], // 使用props接收路由参数
template: '<div>用户信息:{{ uname+ '-----'+ age }}</div>' // 使用路由参数
}
- 示例代码
<section id='app'>
<router-link to="/user/1">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link to="/user/3">User3</router-link>
<router-link to="/login">Login</router-link>
<router-view></router-view>
</section>
const user = {
props: ['id', 'uname', 'age'],
template: '<h1>user组件--用户id为:{{id}} -- 姓名为:{{uname}} -- 年龄为:{{age}}</h1>'
}
const login = {
template:"<div>This is Login组件</div>"
}
const router = new VueRouter({
routes: [
{path: '/login', component: login},
// 如果props被是一个函数,则这个函数接收route对象为自己的形参
{
path: '/user/:id',
component: user,
props: route => ({uname: 'jerry', age: '20', id: route.params.id}),
}]
})
const vm = new Vue({
el: '#app',
router
})
Vue Router 命名路由
- 命名路由的配置规则
- 为了更加方便的表示路由的路径,可以给路由规则起一个别名,即为“命名路由”
- 绑定指向要加:
<router-link :to="{name: 'user', params: {id: 1}}">User1</router-link>
const router = new VueRouter({
routes: [{
path: '/user/:id',
name: 'user',
component: user
}]
})
<router-link :to="{name: 'user', params: {id: 123}}">user</router-link>
router.push({name: 'user', params: {id: 123}})
<section id='app'>
<router-link :to="{name: 'user', params: {id: 1}}">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link to="/user/3">User3</router-link>
<router-link to="/login">Login</router-link>
<router-view></router-view>
</section>
const user = {
props: ['id', 'uname', 'age'],
template: '<h1>user组件--用户id为:{{id}} -- 姓名为:{{uname}} -- 年龄为:{{age}}</h1>'
}
const login = {
template:"<div>This is Login组件</div>"
}
const router = new VueRouter({
routes: [
{path: '/login', component: login},
// 如果props被是一个函数,则这个函数接收route对象为自己的形参
{
name: 'user',
path: '/user/:id',
component: user,
props: route => ({uname: 'jerry', age: '20', id: route.params.id}),
}]
})
const vm = new Vue({
el: '#app',
router
})
Vue Router 编程式导航
-
页面导航的两种方式
- 声明式导航:通过点击链接实现导航的方式,叫做声明式导航
- 例如:普通网页中的
<a></a>
链接或vue中的<router-link></router-link>
- 例如:普通网页中的
- 编程式导航:调用js的api方式实现导航
- 例如:普通网页中的location.href
- 声明式导航:通过点击链接实现导航的方式,叫做声明式导航
-
编程式导航基本用法
- 常用的编程式导航API如下:
this.$router.push('hash地址')
this.$router.go(n)
- 常用的编程式导航API如下:
// 核心代码
const user = {
template: '<div><button @click="goRegister">跳转到注册页面</button></div>',
methods: {
goRegister: function(){
this.$router.push('/register');
}
}
}
<section id='app'>
<router-link :to="{name: 'user', params: {id: 1}}">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link to="/user/3">User3</router-link>
<router-link to="/register">register</router-link>
<router-view></router-view>
</section>
const user = {
props: ['id', 'uname', 'age'],
template: `<div>
<h1><button @click="goRegister">跳转到注册页面</button></h1>
</div>`,
methods: {
goRegister: function(){
this.$router.push('/register')
}
}
}
const register = {
template: `<div>
<h1><button @click="goUser">后退到用户页面</button></h1>
</div>`,
methods: {
goUser: function(){
this.$router.go(-1)
}
}
}
const router = new VueRouter({
routes: [
{path: '/register', component: register},
// 如果props被是一个函数,则这个函数接收route对象为自己的形参
{
name: 'user',
path: '/user/:id',
component: user,
props: route => ({uname: 'jerry', age: '20', id: route.params.id}),
}]
})
const vm = new Vue({
el: '#app',
router
})
- 编程式导航参数规则
router.push()
方法的参数规则- 字符串(路径名称)
router.push('/home')
- 对象
router.push({push: '/home'})
- 命名的路由(传递参数)
- router.push({name: '/user', params: {userId: 123}})
- 带查询参数,变成 /register?uname=sunny
- router.push({path: '/register', query: {uname: 'sunny'}})