开启路由新篇章
前段路由介绍
vue+vue-router 主要是来做单页面应用(Single Page Application)
为什么要做单页面应用:
- 传统的开发方式url改变后立马发送请求到后端,响应整个页面,有可能资源过多,传统开发会让前端整个页面出现“白屏”,用户体验不好
- SPA(单页面应用):锚点值的改变后,不会立刻发送请求,而是在某个合适的时机,发送ajax请求,局部改变页面中的数据,页面不立刻跳转,用户体验好。
前段路由原理
- 锚点值(锚点值就是a标签的href属性) 监视
- ajax获取动态的数据
- 核心点是锚点值的改变
访问#/login
的时候让其进入登录页面,访问#/register
时进入注册页面。
onhashchange
事件,是url上的锚点数据改变就会触发这个事件,锚点数据就是:#/xxx
。页面是不跳转的,只在当前页面渲染,是局部的数据刷新。
代码1
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
*{
padding: 0,
margin:0;
}
</style>
</head>
<body>
<a href="#/login">登录</a>
<a href="#/register">注册</a>
<div id='app'>
</div>
<script type="text/javascript">
// 监视锚点值发生变化,触发事件,
window.onhashchange = function(){
console.log(location.hash);
}
</script>
</body>
</html>
代码2
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
*{
padding: 0;
margin:0;
}
#app{
width: 300px;
height: 400px;
background-color: yellow;
}
</style>
</head>
<body>
<a href="#/login">登录</a>
<a href="#/register">注册</a>
<div id='app'>
</div>
<script type="text/javascript">
// 监视锚点值发生变化,触发事件
var oDiv = document.getElementById('app');
window.onhashchange = function(){
console.log(location.hash);
// 根据不同的锚点值,对页面进行切换
switch (location.hash){
case '#/login':
oDiv.innerHTML = '<h2>登录页面</h2>';
break;
case '#/register':
oDiv.innerHTML = '<h2>注册页面</h2>';
break;
default:
break;
}
}
</script>
</body>
</html>
vue-router的基本使用
是vue中的核心插件,下载:
- 在项目根目录
npm init --yes
npm install vue-router --save
使用:
1.引入 vue-router的对象<script type="text/javascript" src="./node_modules/vue-router/dist/
2.让vue使用该VueRouter创建Vue.use(VueRouter)
3.创建一个路由对象,路由对象中使用的组件一定要在创建路由对象之前声明。
4.router
对象挂载到vue实例化对象中。
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
*{
padding: 0;
margin:0;
}
</style>
</head>
<body>
<div id='app'>
</div>
<script type="text/javascript" src="./vue.js"></script>
<!-- 1.引入 vue-router的对象 -->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<!-- vue-router.js返回的是全局的VueRouter对象。 还提供了两个全局组件 router-link router-view.-->
<script type="text/javascript">
// 2.让vue使用该VueRouter创建
Vue.use(VueRouter)
var Login = {
template:`
<div>登录组件</div>
`
}
var Register = {
template:`
<div>注册组件</div>
`
}
// 3.创建一个路由对象
var router = new VueRouter({
// 配置路由对象
// 数组中存放各个路由
routes:[
{
// 访问path路由时,加载一个Login组件
path: '/login',
component:Login
},
{
path: '/register',
component:Register
}
]
})
var App = {
template:`
<div>
<!-- router-link默认会被渲染成a标签, to属性默认会被渲染成href属性。 -->
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
<!-- router-view, 路由组件的出口 -->
<router-view></router-view>
</div>
`,
}
new Vue({
el:'#app',
template:`<App />`,
components:{
App
},
// 4.挂载router对象,key,value一样可以缩写,router:router等价于router
router:router,
})
</script>
</body>
</html>
流程分析:
点击登录
命名路由
给路由起个名字。
1.给当前的配置路由信息对象设置name: 'login'
属性
2.:to="name:'login'"
var router = new VueRouter({
// 配置路由对象
// 数组中存放各个路由
routes:[
{
// 访问path路由时,加载一个Login组件
path: '/login',
name: 'login', // 1. 给路由起名字
component:Login
},
{
path: '/register',
name: 'register',
component:Register
}
]
})
var App = {
template:`
<div>
<!-- 2. 使用v-bind绑定,name的value必须是字符串 -->
<router-link :to="{name:'login'}">登录</router-link>
<router-link :to="{name:'register'}">注册</router-link>
<!-- router-view, 路由组件的出口 -->
<router-view></router-view>
</div>
`,
}
路由范式,params和query使用
- xxx.html#/user/1, 相当于给了一个参数
params
- xxx.html#/user?userID=1, 表示查询,
query
代码,属于声明式
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
*{
padding: 0;
margin:0;
}
</style>
</head>
<body>
<div id='app'>
</div>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<script type="text/javascript">
Vue.use(VueRouter)
var USerParams = {
template:`
<div>我是用户1</div>
`,
created(){
// 可以使用this.$route.params.userId拿到动态路由的参数
console.log(this.$route);
console.log(this.$router);
},
}
var UserQuery = {
template:`
<div>我是用户2</div>
`,
created(){
// 可以使用this.$route.query.userId拿到query的参数
console.log(this.$route);
console.log(this.$router);
},
}
var router = new VueRouter({
routes:[
{
// 1. 动态的路由参数,以:号开头。
path: '/user/:userId',
name: 'userp',
component:USerParams
},
{
// 2 query的书写
path: '/user',
name: 'userq',
component:UserQuery
}
]
})
var App = {
template:`
<div>
<!--3. 在链接的to属性中添加params键值对 -->
<router-link :to="{name:'userp', params:{userId:1}}">用户1</router-link>
<!--4. 在链接的to属性中添加params键值对 -->
<router-link :to="{name:'userq', params:{userId:2}}">用户2</router-link>
<router-view></router-view>
</div>
`,
}
new Vue({
el:'#app',
template:`<App />`,
components:{
App
},
// 4.添加router对象,key,value一样可以写一个,router:router等价于router
router:router,
})
</script>
</body>
</html>
图解 代码:
页面效果:
编程式导航
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
*{
padding: 0;
margin:0;
}
</style>
</head>
<body>
<div id='app'>
</div>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<script type="text/javascript">
Vue.use(VueRouter)
var USerParams = {
template:`
<div>我是用户1</div>
`,
created(){
// 可以使用this.$route.params.userId拿到动态路由的参数
console.log(this.$route.params.userId);
console.log(this.$router);
},
}
var UserQuery = {
template:`
<div>我是用户2</div>
`,
created(){
// 可以使用this.$route.query.userId拿到query的参数
console.log(this.$route.query.userId);
console.log(this.$router);
},
}
var router = new VueRouter({
routes:[
{
path: '/user/:userId',
name: 'userp',
component:USerParams
},
{
path: '/user',
name: 'userq',
component:UserQuery
}
]
})
var App = {
template:`
<div>
<button @click="paramsHandle">用户1</button>
<button @click="queryHandle">用户2</button>
<router-view></router-view>
</div>
`,
methods:{
paramsHandle(){
// 编程式,name是命名路由的名字,params是参数
this.$router.push({name:'userp', params:{userId:123}})
},
queryHandle(){
this.$router.push({name:'userq', query:{userId:234}})
}
}
}
new Vue({
el:'#app',
template:`<App />`,
components:{
App
},
// 4.添加router对象,key,value一样可以写一个,router:router等价于router
router:router,
})
</script>
</body>
</html>
页面显示:
嵌套路由
一个router-view嵌套另外一个router-view.
需求:进入首页后,有两个按钮,点击音乐访问/home/music,点击电影访问/home/movie
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
*{
padding: 0;
margin:0;
}
</style>
</head>
<body>
<div id='app'>
</div>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<script type="text/javascript">
Vue.use(VueRouter)
var Home = {
template:`
<div>
<router-link to="/home/music">音乐</router-link>
<router-link to="/home/movie">电影</router-link>
<!-- Musci和Movie组件出口 -->
<router-view></router-view>
</div>
`,
}
var Music = {
template:`
<div>我是音乐</div>
`
}
var Movie = {
template:`
<div>我是电影</div>
`
}
var router = new VueRouter({
routes:[
{
path: '/home',
name: 'home',
component:Home,
// 嵌套路由,会自动和/home拼接为/home/music,/home/movie
children:[
{
path: 'music',
component:Music
},
{
path: 'movie',
component:Movie
}
]
},
]
})
var App = {
template:`
<div>
<router-link :to="{name:'home'}">首页</router-link>
<!--首页组件出口 -->
<router-view></router-view>
</div>
`,
methods:{
}
}
new Vue({
el:'#app',
template:`<App />`,
components:{
App
},
router:router,
})
</script>
</body>
</html>
流程图解
页面效果
页面的改进:
1.在页面中访问首页,只显示首页,首页下面的内容没有显示
2.在点击首页的时候才会显示,首页下面的内容
3.希望在访问首页时,默认把音乐和电影两个链接显示出来
在路由配置对象中进行设置,添加一个路由,在访问/时重定向到子路由。
var router = new VueRouter({
routes:[
// 添加一个路由 ,访问/时,重定向到/home
{
path: '/',
redirect:'/home'
// redirect:{name:'home'} // 也可以是个对象
},
{
path: '/home',
name: 'home',
component:Home,
// 嵌套路由,会自动和/home拼接为/home/music,/home/movie
children:[
{
path: 'music',
component:Music
},
{
path: 'movie',
component:Movie
}
]
},
]
})
4.希望在访问首页时,默认把音乐下面的内容展示出来。
在子路由中进行配置
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
*{
padding: 0;
margin:0;
}
</style>
</head>
<body>
<div id='app'>
</div>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<script type="text/javascript">
Vue.use(VueRouter)
var Home = {
template:`
<div>
<router-link to="/home/music">音乐</router-link>
<router-link to="/home/movie">电影</router-link>
<!-- Musci和Movie组件出口 -->
<router-view></router-view>
</div>
`,
}
var Music = {
template:`
<div>我是音乐</div>
`
}
var Movie = {
template:`
<div>我是电影</div>
`
}
var router = new VueRouter({
routes:[
{
path: '/',
redirect:'/home'
},
{
path: '/home',
name: 'home',
component:Home,
children:[
{
// 当访问/home时,Home组件中template中的出口是不会渲染任何内容的。这是因为没有 匹配到合适的子路由
path:'', // 表示匹配到/home
component: Music // 匹配到这个路由时,直接 渲染Music组件到路由出口
},
{
path: 'music',
component:Music
},
{
path: 'movie',
component:Movie
}
]
},
]
})
var App = {
template:`
<div>
<router-link :to="{name:'home'}">首页</router-link>
<!--首页组件出口 -->
<router-view></router-view>
</div>
`,
methods:{
}
}
new Vue({
el:'#app',
template:`<App />`,
components:{
App
},
router:router,
})
</script>
</body>
</html>
图解代码:
页面显示:
动态路由匹配
动态修改路由加载的是同一个组件,展示不同的数据。
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
*{
padding: 0;
margin:0;
}
</style>
</head>
<body>
<div id='app'>
</div>
<script type="text/javascript" src="./vue.js"></script>
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<script type="text/javascript">
Vue.use(VueRouter)
var Timeline = {
template:`
<div>
<router-link :to="{name:'comdes', params:{id:'android'}}">安卓</router-link>
<router-link :to="{name:'comdes', params:{id:'frontend'}}">前端</router-link>
<router-view></router-view>
</div>
`
}
var Pins = {
template:`
<div>我是沸点</div>
`
}
// 共同的子组件
var ComDesc = {
data(){
return {
msg: ''
}
},
template:`
<div>公共组件{{msg}}</div>
`,
watch: {
// 2.检测路由对象的变化。to子去哪个路由,from是从哪个路由来
$route(to, from) {
// 对路由变化作出响应...
console.log(to)
console.log(from)
// 拿到params参数
this.msg = to.params.id
}
}
}
var router = new VueRouter({
routes:[
{
path: '/',
redirect:'/Timeline'
},
{
path: '/timeline',
component:Timeline,
children:[
{
path: '',
component: ComDesc
},
{
// 1.多个router-link匹配到此路由,渲染相同的组件。
path: '/timelin/:id',
name: 'comdes',
component: ComDesc
}
]
},
{
path: '/pins',
component:Pins
},
]
})
var App = {
template:`
<div>
<router-link to="/timeline">首页</router-link>
<router-link to="/pins">沸点</router-link>
<!--首页组件出口 -->
<router-view></router-view>
</div>
`,
methods:{
}
}
new Vue({
el:'#app',
template:`<App />`,
components:{
App
},
router:router,
})
</script>
</body>
</html>
为什么不适用声明周期钩子函数created
来检测,是因为官网如下所说:
当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route 对象:
当router切换时,都是同一个组件,不会再重复的销毁再创建,所以created
钩子函数只会被调用一次。
keep-alive在路由中的使用
内部组件,保持缓存活跃的状态。保持原来组件的一个缓存。
切换路由的时候,会加载不同的组件,也就意味着有组件的创建和销毁的过程。
将我们的组件出口用<keep-alilve><router-view></router-view></keep-alive>
包起来就行了.
生命流程中走激活和停用。