路由的基本概念与原理
路由
路由是一个广义和抽象的概念,路由的本质就是对应关系
在开发中,路由分为:
- 后端路由
- 前端路由
后端路由
- 概念:根据不同的用户URL请求,返回不同的内容
- 本质:URL请求地址与服务器资源之间的对应关系
SPA(Single Page Application)
- 后端渲染(存在性能问题比如:多次交互频繁刷新)
- Ajax前端渲染(前端渲染提高性能,但不支持浏览器的前进后退操作)
- SPA单页面应用程序:整个网站只有一个页面,内容的变化通过Ajax局部更新实现,同时支持浏览器地址栏的前进和后退操作
- SPA实现原理之一:基于URL地址的hash(hash的变化会导致浏览器记录访问历史的变化,但hash的变化不会触发新的URL请求)
在实现SPA过程中,最核心的技术点就是前端路由
前端路由
- 概念:根据不同的用户事件,显示不同的页面内容
- 本质:用户事件与事件处理函数之间的对应关系
实现简易前端路由
- 基于URL中的hash实现
//监听window的onhashchange事件,根据获取得到的最新的hash值
window.onhashchange = function(){
//通过location.hash获取到最新的hash值
}
Vue Router
Vue Router是Vue.js官方的路由管理器。
它和Vue.js的核心深度集成,可以非常方便的用于SPA应用程序的开发。
Vue Router包含的功能有:
- 支持HTML5历史模式或hash模式
- 支持嵌套路由
- 支持路由参数
- 支持编程式路由
- 支持命名路由
vue-router的基本使用
基本使用步骤
- 引入相关的库文件
<!-- 导入vue文件,为全局window对象挂载Vue构造函数 -->
<script src="js/vue.js"></script>
<!-- 导入vue-router文件,为全局window对象挂载VueRouter构造函数 -->
<script src="js/vue-router.js"></script>
- 添加路由链接
<!-- router-link是vue中提供的标签,默认会被渲染为a标签 -->
<!-- to属性会被默认渲染为href属性 -->
<!-- ro属性的值会被默认渲染为#开头的hash地址 -->
<router-link to='/user'></router-link>
<router-link to='/register'></router-link>
- 添加路由填充位
<!-- 路由填充位(也叫做路由占位符) -->
<!-- 将来通过路由规则匹配到的组件,将会被渲染到router-view所在位置 -->
<router-view></router-view>
- 定义路由组件
const User={
template:'<h1>User组件</h1>'
}
const Register={
template:'<h1>Register组件</h1>'
}
- 配置路由规则并创建路由实例
// 创建路由实例对象
const router = new VueRouter({
//路由规则,每个路由规则都是一个配置对象,其中至少包含path和component两个属性
//path 表示当前路由规则匹配的hash地址
//component表示当前路由规则对应要展示的组件
routes:[
{path:'/user',component:User},
{path:'/register',component:Register}
]
});
- 把路由挂载到Vue根实例中
// 创建vm实例
const vm = new Vue({
//指定控制的区域
el: '#app',
data: {},
//挂载路由实例对象
// router:router可简写
router
});
路由重定向
路由重定向指的是:用户在访问地址A的时候,强制用户跳转到地址C,从而展示特定的组件页面
通过路由规则的redirect属性,指定一个新的路由地址,可以很方便地设置路由的重定向:
const router = new VueRouter({
routes:[
//重定向网页打开默认的组件
{path:'/',redirect:'/user'},
{path:'/user',component:User},
{path:'/register',component:Register}
]
});
vue-router嵌套路由
嵌套路由用法
- 嵌套路由功能分析
- 点击父级路由链接显示模板内容
- 模板内容中又有子级路由链接
- 点击子级路由链接显示子级模板内容
- 父路由组件模板
- 父级路由链接
- 父组件路由填充位
- 子级路由模板
- 子路由链接
- 子级路由填充位
const Register = {
template: `<div>
<h1>Register组件</h1>
<hr/>
<router-link to='/user'>Tab1</router-link>
<router-link to='/register'>Tab2</router-link>
<!-- 路由填充位 -->
<router-view >
</div>`
}
- 嵌套路由配置
- 父级路由通过children属性配置子级路由
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}
]
}
]
});
vue-router动态路由匹配
动态匹配路由的基本用法
应用场景:通过动态路由参数的模式进行路由匹配
const router = new VueRouter({
routes:[
//动态路径参数,以冒号开头
{path:'/user/:id',component:User}
]
});
路由组件中通过$route.params获取路由参数
const User={
template:'<div>User{{$route.params.id}}</div>'
}
路由组件传递参数
$route与对应路由形成高度耦合,不够灵活,所以可以使用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>User{{id}}</div>'//使用路由参数
}
- props的值为对象类型
const router = new VueRouter({
routes:[
//如果props是一个对象,它会被按原样设置为组件属性
{path:'/user/:id',component:User,props:{uname:'list',age:12}}
]
});
const User={
props:['uname','age'],//使用props接收路由参数,此时接收不了id
template:'<div>User{{unama+'---'+age}}</div>'//使用路由参数
}
- props的值为函数类型
const router = new VueRouter({
routes:[
//如果props是一个函数,则这个函数接收route对象为自己的形参
{path:'/user/:id',
component:User,
props:route=>({uname:'tkrj',age:19,id:route.params.id})}
]
});
const User={
props:['uname','age','id'],
template:'<div>User{{id+'---'+unama+'---'+age}}</div>'//使用路由参数
}
vue-router命名路由
命名路由:为了更加方便的表示路由的路径,可以给路由规则起一个别名
命名路由的配置规则
const router = new VueRouter({
routes:[
{
path:'/user/:id',
//name属性命名
name:'user',
component:User
}
]
});
<!-- 注意加冒号 -->
<router-link :to="{name:'user',params:{id:123}}">User</router-link>
vue-router编程式导航
页面导航的两种方式
-
声明式导航:通过点击链接实现导航的方式(先声明了链接再实现了导航)
例如:普通网页中的<a></a>
链接或vue中的<router-link></router-link>
-
编程式导航:通过调用JavaScript形式的API实现导航的方式
例如:普通网页中的location.href
编程式导航基本用法
常用的编程式导航API:
- this.$router.push(‘hash地址’)
const User = {
template:'<div><button @click="goRegister">跳转到注册页面</button></div>',
methods:{
goRegister:function(){
//用编程方式控制路由跳转
this.$router.push('/register');
}
}
}
- this.$router.go(n) //常用来实现前进后退
const Register = {
template:'<div><button @click="goBack">后退</button></div>',
methods:{
goBack:function(){
//用编程方式控制路由跳转
this.$router.go(-1);
}
}
}
编程式导航参数规则
router.push()方法的参数规则
// 字符串(路径名称)
router.push('/home')
// 对象
router.push({path:'/home'})
// 命名的路由(传递参数)
router.push({name:'/user',params:{userId:123}})
// 带查询参数,变成/register?uname=tkrj
router.push({path:'/register',query:{uname:'tkrj'}})
命名视图
命名视图与组件化开发中讲解的具名插槽很像,都是让不同的出口显示不同的内容。命名视图就是和当前路由地址被匹配的时候同时指定多个出口,并且每个出口中显示的内容不一样。
<!-- 路由填充位(也叫做路由占位符) -->
<!-- 和匿名插槽运用,如果指定多个填充位,当路由地址被匹配后,多个填充位显示的内容一样 -->
<!-- 因此给填充位起名 -->
<router-view name = "name1"></router-view>
<router-view name = "name2"></router-view>
// 创建路由实例对象
const router = new VueRouter({
//path 表示当前路由规则匹配的hash地址
//component表示当前路由规则对应要展示的组件
routes:[
{
path:'/user',
component:[
name1: user,
name2: user2
]}
]
});