一、前端路由vue-router介绍

  Vue-Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:

  • 嵌套的路由/视图表
  • 模块化的、基于组件的路由配置
  • 路由参数、查询、通配符
  • 基于 Vue.js 过渡系统的视图过渡效果
  • 细粒度的导航控制
  • 带有自动激活的 CSS class 的链接
  • HTML5 历史模式或 hash 模式,在 IE9 中自动降级
  • 自定义的滚动条行为

  vue + vue-router 主要是用来做 单页面应用(Single Page Application)

1、为什么要做单页面应用?

(1)传统的开发方式

  url改变后,立马发送请求,响应整个页面,有可能资源过多,传统的开发会让前端的页面出现“白屏”。

  用户体验不好。

(2)SPA单页面应用

  SPA:Single Page Application

  锚点值改变后,不会立刻发送请求,而是在某个合适的时机,发送ajax请求,局部改变页面中的数据。

  页面不立刻跳转,用户体验好。

2、前端路由的实现原理

  前端路由:

     1.锚点值监视; 2.ajax获取动态的数据; 3.核心点是锚点值的改变;

  前端中的 vue/react/angular 都很适合做单页面应用。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="#/login">登录页面</a>
<a href="#/register">注册页面</a>
<div id="app"> </div>
<script type="text/javascript">
// 获取div
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:
// statements_def
break;
}
}
</script>
</body>
</html>

(1)window.onhashchange介绍

  当一个窗口的 hash (URL中'#'后面的部分)改变时就会触发 onhashchange 事件。

  onhashchange 事件在当前url的锚点部分(以'#'号为开始)发生改变时触发。

  锚部分的实例:指定当前URL为http://www.example.com/test.htm#part2 - 这个 URL 中的锚部分为 #part2。

(2)onhashchange调用事件方法

3、根据不同锚点切换页面效果

(1)初始页面显示如下:

  

(2)点击登录页面

  

(3)点击注册页面

  

二、vue-router使用

1、用NPM下载安装vue-router

(venv) MacBook-Pro:vue_study hqs$ cd 03-vue-router/
(venv) MacBook-Pro:03-vue-router hqs$ ls
01-前端路由实现原理.html vue.js
(venv) MacBook-Pro:03-vue-router hqs$ npm init --yes
Wrote to /Users/hqs/PycharmProjects/vue_study/03-vue-router/package.json: {
"name": "03-vue-router",
"version": "1.0.0",
"description": "",
"main": "vue.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
} (venv) MacBook-Pro:03-vue-router hqs$ npm install vue-router -S
03-vue-router@1.0.0 /Users/hqs/PycharmProjects/vue_study/03-vue-router
└── vue-router@3.0.1 npm WARN 03-vue-router@1.0.0 No description
npm WARN 03-vue-router@1.0.0 No repository field.

  查看项目文件目录:

  

2、vue-router应用实例

<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>
<!--全局的VueRouter对象 vue-router还提供了两个全局的组件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', // login路由
component:Login
},
{
path:'/register',
component:Register
}
]
}); var App = { // App:入口组件
// router-link默认会被渲染为a标签,to属性默认会被渲染为href属性
// router-view是路由组件的出口
template:`
<div>
<router-link to="/login">登录页面</router-link>
<router-link to="/register">注册页面</router-link>
<router-view></router-view>
</div>
`
}; new Vue({ // Vue实例化对象
el:'#app',
components:{
App
},
router, // router:router, 在key和value相同时可以只写一个
template:`<App/>` // 入口组件
});
</script>
</body>

注意要点

(1)<router-link>组件和<router-view>组件

  全局的VueRouter对象 vue-router 还提供了两个全局的组件router-link / router-view。

  <router-link> 组件支持用户在具有路由功能的应用中 (点击) 导航。 通过 to 属性指定目标地址,默认渲染成带有正确链接的 <a> 标签,可以通过配置 tag 属性生成别的标签.。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的 CSS 类名。

  <router-view> 组件是一个 functional 组件,渲染路径匹配到的视图组件,是所有路由组件的出口。<router-view> 渲染的组件还可以内嵌自己的 <router-view>,根据嵌套路径,渲染嵌套组件。

var App = {
// router-link默认会被渲染为a标签 to属性默认会被渲染为href属性
// router-view是路由组件的出口
template:`
<div>
<router-link to="/login">登录页面</router-link>
<router-link to="/register">注册页面</router-link> <router-view></router-view>
</div>
`
};

(2)报错Cannot read property 'matched' of undefined

  

  这种问题就是因为自己创建的router对象没有被Vue实例化对象所使用:

new Vue({   // Vue实例化对象
el:'#app',
components:{
App
},
router, // router:router, 在key和value相同时可以只写一个
template:`<App/>` // 入口组件
});

(3)页面通过router-view渲染

  1)点击前效果:

  

  可以看到router-link默认会被渲染为a标签,to属性默认会被渲染为href属性。

  2)点击后效果:

  

(4)小结  

  当你在页面访问login时,router-link对应着的路径是'/login',加载对应的component组件:Login,component组件找一个出口渲染出来:router-view。

  

3、命名路由

  有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。你可以在创建 Router 实例的时候,在 routes 配置中给某个路由设置名称。

  给当前的配置路由信息对象设置name属性。

  对上面代码做如下修改:

var router = new VueRouter({
// 配置路由对象
routes:[
{
path:'/login',
name:'login', // 设置路由名称
component:Login
},
{
path:'/register',
name:'register', // 设置路由名称
component:Register
}
]
}); var App = {
// 不使用to属性访问路由,改用动态命名路由绑定
// 要链接到一个命名路由,可以给 router-link 的 to 属性传一个对象:
template:`
<div>
<router-link :to="{name:'login'}">登录页面</router-link>
<router-link :to="{name:'register'}">注册页面</router-link>
<router-view></router-view>
</div>
`
};

4、总结Vue Router流程

(1)引入vue-router对象模块

<script type="text/javascript" src="vue.js"></script>
<!--引入vue-router的对象-->
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>

  该模块默认会抛出一个VueRouter对象,另外还有两个全局的组件router-link和router-view。

(2)让Vue使用该VueRouter创建

// 如果使用模块化机制编程,导入Vue和VueRouter,要调用Vue.use(VueRouter)

<script type="text/javascript">

    // 让Vue使用该VueRouter创建
Vue.use(VueRouter); // 代码省略
</script>

(3)创建路由对象

// 3.创建一个路由对象
var router = new VueRouter({
// 配置路由对象
routes:[
{
path:'/login',
name:'login', // 设置路由名称
component:Login
},
{
path:'/register',
name:'register', // 设置路由名称
component:Register
}
]
});

(4)路由对象挂载到vue实例化对象中

var App = {
// 不使用to属性访问路由,改用动态命名路由绑定
// 要链接到一个命名路由,可以给 router-link 的 to 属性传一个对象:
template:`
<div>
<router-link :to="{name:'login'}">登录页面</router-link>
<router-link :to="{name:'register'}">注册页面</router-link>
<router-view></router-view>
</div>
`
}; new Vue({
el:'#app',
components:{
App
},
router, // router:router, 在key和value相同时可以只写一个
template:`<App/>`
});

三、路由参数(范式)

  在vue-router路由中,传参方式一般分两种。如下所示:

(1)xxx.html#/user/1            params 动态路由参数
(2)xxx.html#/user?userId=2 query 查询

  示例代码如下所示:

<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>
<!--全局的VueRouter对象 vue-router还提供了两个全局的组件router-link / router-view-->
<script type="text/javascript">
// 路由范式
//(1)xxx.html#/user/1 params 动态路由参数
//(2)xxx.html#/user?userId=2 query 查询 // 2.让Vue使用该VueRouter创建
Vue.use(VueRouter); var UserParams = {
template:`
<div>我是用户1</div>
`,
created(){
// 接收参数
console.log(this.$route); // 其中包含params属性
console.log(this.$route.params.userId); // 输出:1
// 传参,发送ajax请求
console.log(this.$router); // VueRouter对象
}
}; var UserQuery = {
template:`
<div>我是用户2</div>
`,
created(){
// 接收参数
console.log(this.$route); // 包含query属性,query: {userId: "2"}
console.log(this.$route.query.userId); // 输出:2 // 传参,发送ajax请求
console.log(this.$router); // VueRouter对象
}
}; // 3.创建一个路由对象
var router = new VueRouter({
// 配置路由对象
routes:[
{
path:'/user/:userId', // params形式,动态路由参数,以冒号开头
name:'userp', // 设置路由名称
component:UserParams
},
{
path:'/user',
name:'userq', // 设置路由名称
component:UserQuery
}
]
}); var App = {
// 不使用to属性访问路由,改用动态命名路由绑定.要链接到一个命名路由,可以给 router-link 的 to 属性传一个对象
// 路由匹配,query是查询操作
template: `
<div>
<router-link :to="{name:'userp', params:{userId:1}}">用户1</router-link>
<router-link :to="{name:'userq', query:{userId:2}}">用户2</router-link>
<router-view></router-view>
</div>
`
}; new Vue({
el:'#app',
components:{
App
},
router, // router:router, 在key和value相同时可以只写一个
template:`<App/>`
});
</script>
</body>

1、query方式传参和接收参数

  利用$route.query对象的Get方式传参,与http的get方式一样,会将参数暴露到地址栏。

var UserQuery = {
template:`
<div>我是用户2</div>
`,
created(){
// 接收参数
console.log(this.$route); // 包含query属性,query: {userId: "2"}
console.log(this.$route.query.userId); // 输出:2 // 传参,发送ajax请求
console.log(this.$router); // VueRouter对象
}
};

  显示效果如下:

  

2、params方式传参和接收参数

  利用$route.params对象的Post方式传参,该方式具有一定限制,必须通过路径传参方式。

var UserParams = {
template:`
<div>我是用户1</div>
`,
created(){
// 接收参数
console.log(this.$route); // 其中包含params属性
console.log(this.$route.params.userId); // 输出:1
// 传参,发送ajax请求
console.log(this.$router); // VueRouter对象
}
};

  显示效果如下所示:

  

3、源码分析

// vue-router.js文件558行到564行
Object.defineProperty(Vue.prototype, '$router', {
get: function get () { return this._routerRoot._router }
}); Object.defineProperty(Vue.prototype, '$route', {
get: function get () { return this._routerRoot._route }
});

  相当于给vue实例化对象添加了两个属性$router(VueRouter)和$route(路由配置信息)。

4、配置路由对象方式

// 3.创建一个路由对象
var router = new VueRouter({
// 配置路由对象
routes:[
{
path:'/user/:userId', // params形式,动态路由参数,以冒号开头
name:'userp', // 设置路由名称
component:UserParams
},
{
path:'/user',
name:'userq', // 设置路由名称
component:UserQuery
}
]
});

  注意params形式,是配置动态路由参数,要以冒号开头。

5、匹配路由

var App = {
// 不使用to属性访问路由,改用动态命名路由绑定.要链接到一个命名路由,可以给 router-link 的 to 属性传一个对象
template:`
<div>
<router-link :to="{name:'userp', params:{userId:1}}">用户1</router-link>
<router-link :to="{name:'userq', query:{userId:2}}">用户2</router-link>
<router-view></router-view>
</div>
`
};

  访问效果如下所示:

  

四、编程式导航 

  除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。

1、编程式导航示例

  对上例做如下修改,不再使用声明式的<router-link :to='...'>,改为使用编程式:router.push(...)

var App = {
// 不使用to属性访问路由,改用动态命名路由绑定.要链接到一个命名路由,可以给 router-link 的 to 属性传一个对象
template:`
<div>
<button @click="paramsHandler">用户1</button>
<button @click="queryHandler">用户2</button> <router-view></router-view>
</div>
`,
methods:{
paramsHandler(){
// 编程式导航
this.$router.push({ name: 'userp', params: { userId: 123 }})
},
queryHandler(){
this.$router.push({ name: 'userq', query: {userId: 3221} })
}
}
};

  params访问显示效果:

  

  query访问显示效果:

  

2、router.push(location, onComplete?, onAbort?)

  注意:在 Vue 实例内部,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push

  想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

  当你点击 <router-link> 时,这个方法会在内部调用,所以说,点击 <router-link :to="..."> 等同于调用 router.push(...)

  

  该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:

// 字符串
router.push('home') // 对象
router.push({ path: 'home' }) // 命名的路由
router.push({ name: 'user', params: { userId: 123 }}) // 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

  注意:如果提供了 pathparams 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path

const userId = 123
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user

  同样的规则也适用于 router-link 组件的 to 属性。

  在 2.2.0+,可选的在 router.push 或 router.replace 中提供 onComplete 和 onAbort 回调作为第二个和第三个参数。这些回调将会在导航成功完成 (在所有的异步钩子被解析之后) 或终止 (导航到相同的路由、或在当前导航完成之前导航到另一个不同的路由) 的时候进行相应的调用。

  注意:如果目的地和当前路由相同,只有参数发生了改变 (比如从一个用户资料到另一个 /users/1 -> /users/2),你需要使用 beforeRouteUpdate 来响应这个变化 (比如抓取用户信息)

五、嵌套路由

  实际生活中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件,例如:

/user/foo/profile                     /user/foo/posts
+------------------+ +-----------------+
| User | | User |
| +--------------+ | | +-------------+ |
| | Profile | | +------------> | | Posts | |
| | | | | | | |
| +--------------+ | | +-------------+ |
+------------------+ +-----------------+

  借助 vue-router,使用嵌套路由配置,就可以很简单地表达这种关系。

1、嵌套路由示例

<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>
<!--全局的VueRouter对象 vue-router还提供了两个全局的组件router-link / router-view-->
<script type="text/javascript"> // 嵌套路由:
// 需求:进入首页后,点击音乐(/home/music) 电影(/home/movie) // 2.让Vue使用该VueRouter创建
Vue.use(VueRouter); var Home = {
// 子路由出口
template:`
<div>
<br/>
<router-link to="/home/music">音乐</router-link>
<router-link to="/home/movie">电影</router-link> <router-view></router-view>
</div>
`
}; var Music = {
template:`
<div>我是音乐</div>
`
}; var Movie = {
template:`
<div>我是电影</div>
`
}; // 3.创建一个路由对象
var router = new VueRouter({
// 配置路由对象
routes:[
{
path:'/',
redirect:'home'
// redirect:{name:'home'} // 命令路由的方式
},
{
path:'/home', // params形式,动态路由参数,以冒号开头
name:'home', // 设置路由名称
component:Home,
children:[
// 动态路由匹配表示你的子组件中的结构是不同的 // 当访问/home组件时,Home组件的出口是不会渲染任何内容的,
// 这是因为没有匹配到合适的子路由
{
path:'', // 访问空字符串就表示访问/home了
component:Music // 默认加载孩子组件Music
},
{
path:'music', // 自己会默认去拼接斜杠
component:Music // 对应加载的组件
// children: // 可以继续配置三层路由
},
{
path:'movie', // 自己会默认去拼接斜杠
component:Movie // 对应加载的组件
}
]
},
]
}); var App = {
// 路由出口
template:`
<div>
<router-link :to="{name:'home'}">首页</router-link> <router-view></router-view>
</div>
`,
}; new Vue({
el:'#app',
components:{
App
},
router, // router:router, 在key和value相同时可以只写一个
template:`<App/>`
});
</script>
</body>

2、注意要点

(1)以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。

(2)children 配置就是像 routes 配置一样的路由配置数组,所以呢,你可以嵌套多层路由。

3、显示效果

(1)页面首页默认显示音乐

  

(2)点击切换到电影页面

  

4、嵌套路由警告处理

  

  这个警告的意思是:当父路由有子路由时,不允许子路由中有命名路由。因此对代码做如下调整

var router = new VueRouter({
// 配置路由对象
routes:[
{
path:'/',
redirect:'home'
// redirect:{name:'home'} // 命令路由的方式
},
{
path:'/home', // params形式,动态路由参数,以冒号开头
// name:'home', // 设置路由名称
component:Home,
children:[
// 动态路由匹配表示你的子组件中的结构是不同的 // 当访问/home组件时,Home组件的出口是不会渲染任何内容的,
// 这是因为没有匹配到合适的子路由
{
path:'', // 访问空字符串就表示访问/home了
component:Music // 默认加载孩子组件Music
},
{
path:'music', // 自己会默认去拼接斜杠
component:Music // 对应加载的组件
// children: // 可以继续配置三层路由
},
{
path:'movie', // 自己会默认去拼接斜杠
component:Movie // 对应加载的组件
}
]
},
]
}); var App = {
// 路由出口
template:`
<div>
<!--<router-link :to="{name:'home'}">首页</router-link>-->
<router-link to="/home">首页</router-link>
<router-view></router-view>
</div>
`,
};

  再次查看控制台,警报解除:

  

六、动态路由匹配  

  我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果。

const User = {
template: '<div>User</div>'
} const router = new VueRouter({
routes: [
// 动态路径参数 以冒号开头
{ path: '/user/:id', component: User }
]
})

1、动态路由匹配示例

<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>
<!--全局的VueRouter对象 vue-router还提供了两个全局的组件router-link / router-view-->
<script type="text/javascript">
// 2.让Vue使用该VueRouter创建
Vue.use(VueRouter); var Timeline = {
template:`
<div>
<router-link :to="{name:'comDesc', params:{id:'android'}}">Android</router-link>
<router-link :to="{name:'comDesc', params:{id:'frontend'}}">前端</router-link>
<router-view></router-view>
</div>
`
}; var Pins = {
template:`
<div>
我是沸点
</div>
`
}; // 共同的子组件
var ComDesc = {
data(){
return{
msg:''
}
},
template:`
<div>
我是{{msg}}
</div>
`,
created(){ // 生命周期方法
alert(1);
this.msg = '安卓';
}
}; // 3.创建一个路由对象
var router = new VueRouter({
// 配置路由对象
routes:[
// 动态路由参数以冒号开头
{
path:'/timeline',
component:Timeline,
children:[
{
path:"",
component:ComDesc // 访问Timeline时访问共同组件ComDesc
},
{
path:'/timeline/:id',
name:'comDesc',
component:ComDesc // 访问子动态路由时,也加载共同组件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>
`,
}; new Vue({
el:'#app',
components:{
App
},
router, // router:router, 在key和value相同时可以只写一个
template:`<App/>`
});
</script>
</body>

(1)路由映射到公共路由

var router = new VueRouter({
// 配置路由对象
routes:[
// 动态路由参数以冒号开头
{
path:'/timeline',
component:Timeline,
children:[
{
path:"",
component:ComDesc // 访问Timeline时访问共同组件ComDesc
},
{
path:'/timeline/:id',
name:'comDesc',
component:ComDesc // 访问子动态路由时,也加载共同组件ComDesc
} ]
},
{
path:'/pins',
component:Pins
}
]
});

  /timeline/android和/timeline/frontend都将映射相同的路由。

  一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。

(2)组件实例复用

  当使用路由参数时,例如从 /user/foo 导航到 /user/bar原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用

// 共同的子组件
var ComDesc = {
data(){
return{
msg:''
}
},
template:`
<div>
我是{{msg}}
</div>
`,
created(){ // 生命周期方法
alert(1);
this.msg = '安卓';
}
};

(3)显示效果及生命周期钩子不重复调用

  初始状态:

  

  点击首页,显示alert:

  

  点击确认后显示:

  

  点击前端:

   

  再点回安卓或首页,页面显示会调整,但都不再显示alert。说明生命周期钩子不再运行。

2、响应路由参数的变化  

  前面已经说到当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。

  复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route对象:

// 共同子组件
var ComDesc = {
data(){
return{
msg:''
}
},
template:`
<div>
我是{{msg}}
</div>
`,
created(){ // 生命周期方法
// alert(1);
// this.msg = '安卓';
},
watch:{
'$route' (to, from) {
// 对路由变化作出响应...
console.log(to);
console.log(from);
}
}
};

(1)点击安卓页面,打印出的to和from信息

  

(2)然后再点击前端页面,打印的to和from信息

  

(3)直接渲染

var ComDesc = {
data(){
return{
msg:''
}
},
template:`
<div>
我是{{msg}}
</div>
`,
created(){ // 生命周期方法
// alert(1);
// this.msg = 'android';
},
watch:{
'$route' (to, from) {
// 对路由变化作出响应...
console.log(to);
console.log(from); // 直接渲染
this.msg = to.params.id;
}
}
};

  点击显示效果如下所示:

  

  也可以看到组件没有再次被销毁或创建。

七、keep-alive在路由中的使用

  <keep-alive>是Vue的内置组件,能在组件切换过程中将状态保留在内存中(缓存),防止重复渲染DOM。

(1)Props:

  • include:字符串或正则表达式。只有名称匹配的组件会被缓存。
  • exclude:字符串或正则表达式。任何名称匹配的组件都不会被缓存。
  • max:数字。最多可以缓存多少组件实例。

(2)用法:

  <keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 <transition> 相似,<keep-alive> 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。

  当组件在 <keep-alive> 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。

  主要用于保留组件状态或皮面重新渲染。

1、不使用keep-alive切换页面

<script type="text/javascript">
// 2.让Vue使用该VueRouter创建
Vue.use(VueRouter); var Timeline = {
template:`
<div>
我是首页
</div>
`,
created(){
console.log('首页组件创建了');
},
mounted(){
console.log('首页组件DOM加载了');
},
destroyed(){
console.log('首页销毁了');
}
}; var Pins = {
template:`
<div>
<h3 @click="clickHandler">我是沸点</h3>
</div>
`,
methods:{
clickHandler(e){
e.target.style.color = 'red';
}
},
created(){
console.log('沸点组件创建了');
},
mounted(){
console.log('沸点组件DOM加载了');
},
destroyed(){
console.log('沸点销毁了');
}; // 3.创建一个路由对象
var router = new VueRouter({
// 配置路由对象
routes:[
// 动态路由参数以冒号开头
{
path:'/timeline',
component:Timeline,
},
{
path:'/pins',
name:'pins',
component:Pins
}
]
}); var App = {
// keep-alive组件保持缓存,把router-view渲染的出口缓存起来
template:`
<div>
<router-link to="/timeline">首页</router-link>
<router-link to="/pins">沸点</router-link> <router-view></router-view>
</div>
`,
}; new Vue({
el:'#app',
components:{
App
},
router, // router:router, 在key和value相同时可以只写一个
template:`<App/>`
});
</script>

  此时还没有使用keep-alive,切换页面时都会执行生命周期操作:

  

  而且切换到沸点页面,点击“我是沸点”,可以将字体变红,但是切换到首页再切换沸点时,又变黑色了。也说明了重新进行了创建销毁。

2、用keep-alive组件把router-view渲染的出口缓存起来

  注意:<keep-alive> 是用在其一个直属的子组件被开关的情形。如果你在其中有 v-for 则不会工作。如果有上述的多个条件性的子元素,<keep-alive> 要求同时只有一个子元素被渲染。

var App = {
// keep-alive组件保持缓存,把router-view渲染的出口缓存起来
template:`
<div>
<router-link to="/timeline">首页</router-link>
<router-link to="/pins">沸点</router-link> <keep-alive>
<router-view></router-view>
</keep-alive>
</div>
`,
};

  显示效果如下:

  

  可以看到第一次点击会创建和加载,但并没有销毁DOM,从首页切换到沸点,仍保持为红色。

最新文章

  1. jquery实现分页功能
  2. php开发必备小工具
  3. C++多线程3
  4. 安卓开发_慕课网_ViewPager与FragmentPagerAdapter实现Tab实现Tab(App主界面)
  5. node.js环境搭建
  6. AppCan移动技术全景图:创新、协作、支撑
  7. AutoLayout学习之理解intrinsicContentSize,Content Hugging Priority,Content Compression Resistance Priority
  8. javascript常用的内置对象实用操作
  9. boost::pool 库速记
  10. 【linux】安裝 PHP时出现error: Cannot find MySQL header files
  11. [UOJ] #217. 【UNR #1】奇怪的线段树
  12. 【问题汇总】ScrollView嵌套ListView的问题
  13. Snackbar 提醒
  14. JMeter 中_time 函数的使用(时间戳、当前时间)
  15. kubernetes组成
  16. Spring &lt;context:annotation-config&gt; 与&lt;context-component-scan&gt; 的作用
  17. QueenPuzzle-N皇后问题
  18. html/php/mysql乱码
  19. HTML5之全局属性 (声明:内容节选自《HTML 5从入门到精通》)
  20. Nodejs线上日志部署

热门文章

  1. 跟我一起读postgresql源码(二)——Parser(查询分析模块)
  2. 数据结构实验之图论七:驴友计划 ( 最短路径 Dijkstra 算法 )
  3. 使用TortoiseSVN新建及合并分支图文教程
  4. there is already &#39;RtController&#39; bean method 项目报错
  5. C++_类和动态内存分配4-有关返回对象的说明
  6. Jquery动态绑定事件处理函数 bind / on / delegate
  7. POJ - 2018 二分+单调子段和
  8. [转] CSS 颜色名
  9. Android高级工程师面试题整理
  10. 墨菲定律&amp;吉德林法则&amp;吉尔伯特定律&amp;沃尔森法则&amp;福克兰定律