简介
Vue和vue-router 创建 SPA 应用。
vue-router 作用. 通过路由规则,渲染各自的组件。
Vue开发,整个应用已经被拆分成了独立的组件。在使用vue-router时,把路由映射到各个组件。vue-router 把各个组件渲染到正确的地方。
使用的版本:0.7.13
vue-reouter是Vue的一个插件,需要使用Vue.use()
来注册插件。注册到Vue对象上。在vue-router内部会检测window.Vue
对象是否存在。
Vue对象并不会暴露到全局window对象中,而是通过module.exports
形式输出,因此需要使用者手动注册。
基本使用
<body>
<div class="app">
<p>
<a v-link="{ path: '/home' }">HOME</a>
<a v-link="{ path: '/page' }">Page</a>
</p>
<router-view></router-view>
<!-- router-view 会由vue-router 去渲染组件, 将结果挂载到 当前div上 -->
</div>
<script src="vue.js"></script>
<script src="vue-router.min.js"></script>
<script>
// const 组件
var Home = Vue.component('Home', {
template: '<h1>Home, 这是主页</h1>'
});
var Page = Vue.component('page', {
template: '<h1>这是page页面</h1>'
});
// 路由实例
var router = new VueRouter();
router.map({
'/home': {
component: Home
},
'/page': {
component: Page
}
});
// 根组件 // 路由需要一个根组件
var App = Vue.extend({});
// 路由器会创建一个App 实例, 并且挂载到 .app 匹配的元素上.
router.start(App, '.app');
</script>
</body>
嵌套路由
仅有路由跳转需要不够,很多情况下,在同一个页面上,多标签页的切换,在vue-router 中,用嵌套路由。
<body>
<div class="app">
<router-view></router-view>
</div>
<template id="page1">
<div class="page1">
<h2>Page1页面</h2>
<router-view></router-view> <!-- 嵌套的外链 -->
</div>
</template>
<script src="vue.js"></script>
<script src="vue-router.min.js"></script>
<script>
// 组件
var Page1 = Vue.component('Page1', {
template: document.querySelector('#page1').innerHTML
});
var News = Vue.component('News', {
template: '<div>新闻页面</div>'
});
var Imgs = Vue.component('Imgs', {
template: '<div>图片页面</div>'
});
// 路由实例
var router = new VueRouter();
router.map({
'/': {
component: {
template: '<p>主页</p>'
}
},
'/page1': {
component: Page1,
subRoutes: { // 子组件
'/news': {
component: News
},
'/imgs': {
component: Imgs
}
}
}
});
// 根组件
var App = Vue.extend({});
router.start(App, '.app');
</script>
</body>
路由对象
vue-router 对路劲匹配是支持动态片段,全匹配片段,以及查询参数( 片段指是的 URL 中的一部分 )。
对于解析过的路由,这些信息都可以通过路由上下文对象访问。 赋值给 this.$route
,并且当路由切换时,路由对象会自动更新。
$route object
$route.path
返回字符串,返回当前路径/page1/imgs
$route.params
返回对象$route.quer
返回对象 ,路由中查询参数,get请求的键值对$route.router
路由规则所属的路由组件-
$route.matched
返回数组,当前匹配的路径中所有的路径规则.{ "0": { "handler": { "subRoutes": { "/news": { "path": "/news", "fullPath": "/page1/news" }, "/imgs": { "path": "/imgs", "fullPath": "/page1/imgs" } }, "path": "/page1", "fullPath": "/page1" }, "params": {}, "isDynamic": false }, "1": { "handler": { "path": "/imgs", "fullPath": "/page1/imgs" }, "params": {}, "isDynamic": false }, "queryParams": { "a": "b" }, "length": 2 }
$route.name
返回当前路径的名字
路由匹配
动态片段
语法::
冒号开头的路径片段定义。
router.map({
'/': {
component: {
template: '<p>主页</p>'
}
},
'/page1/:name': {
component: Page1,
}
});
'/page1/:name'
中的name
可以匹配任意字段. 例如: /page1/:news
, /page1/:imgs
全匹配片段
动态片段只能匹配路径中的一个部分,而全匹配片段是贪婪模式。
router.map({
'/': {
component: {
template: '<p>主页</p>'
}
},
'/news/*any': {
component: News,
}
});
'/news/*any'
可以匹配例如:/news/a/b/c
,/news/a/b
/foo/*any/bar
可以匹配 例如: /foo/a/b/bar
具名路径
语法: router.map(); 匹配规则, View视图需要 通过v-link
链接到该规则。 也可以通过 router.go(); 来切换到路径中。
作用: 给匹配路径规则添加一个名字,更好操作。
<!-- 具名路径 -->
<a v-link="{ name: 'user', params: { userId: 111 }}">用户名</a>
路由配置
实例化VueRouter时可以出啊如一个可选的VueRouterConfig路由选项对象来自定义路由器的行为。返回rotuer路由器实例,router实例暴露了一些实例属性和实例方法,可以用来控制整个路由应用。
// 路由实例
var router = new VueRouter({
hashbang: true, // 将路径中的 `#!` --> `#`
// history: true, // 设置true 后,启用HTML5 history模式。通过 history.pushState() 和 history.replaceState() 来管理浏览历史记录。
abstract: true, // 使用一个不依赖与浏览器的浏览历史虚拟管理后台。虚拟模式在测试或实际的URL 不重要的时候。
transitionOnLoad: true // 在初次加载时是否对 <trouer-view>处理场景切换效果。 默认情况下,组件在初次加载时会直接渲染。
});
路由选项
hahsbang (布尔值)
默认值为true。当该值为true时,表示匹配的路由在浏览器地址栏中以hash模式显示。例如:假设当前浏览器地址栏中的地址为:http://example.com/path?query
,当用户点击home链接时,浏览器地址栏中地址会显示为:http://example.com/path?query#!/home
history (布尔值)
默认值为false。当该值为true时,会以HTML5 history API 进行导航。
注意:
假如当前页面地址栏为:
http://example.com/home
,而在路由配置中配置了/home/weblcome
路径,那么当用户直接访问http://examle.com/home/welcome
路径时,服务器端应确保返回http://example.com/home
页面,而不是http://example.com/home/weblcom
页面。否则可能出现/home/welcome
页面不存在而返回404错误。当history值为true,不存hashbang值是否为true,总会以history模式进行导航。
当history值为true,而浏览器并不支持HTML5 history API 时,vue-rotuer会自动降级为hashbang模式
saveScrollPosiiton (布尔值)
默认值为false,该值只是在history值为true时生效。当该值设置为true时,在点击浏览器后按退按钮时页面会定位到上一次该路由对应的视图所在位置。
transitionOnLoad (布尔值)
默认值false,当该值为true是,在页面第一次加载时rotuer-view会有路由切换动画,默认为直接渲染。
suppressTransitionError (布尔值)
默认值为false, 当该值为true,在组件路由切换钩子中产生的异常不会被抛出。
linkActiveClass (字符串)
默认值为v-link-active, 表示 v-link 所在元素处于激活状态时 vue-router加在该元素上的类名。
root (字符串)
默认值 null, 该值只在history值为true时,生效。定义路由根路径,所有路径被匹配时,浏览器地址栏URL会显示为根路径+匹配路径。
路由实例属性
app (根组件实例)
vue-rotuer 应用的根Vue实例,由调用 router.satrt(App, '#app'); 时传入的组件构造器App创建得到。
mode(字符串)
可能值有html5
,hash
,abstract
html5: 当创建rotuer实例时,所有配置对象history值为true,并且浏览器支持HTML5 histroy API时。
hash : 当创建rotuer实例时,所传配置hash值为true,或者history值为true,当时浏览器不支持HTML history API时。
abstract: 当宿主环境中没有window对象(例如非浏览器环境)时,会自动退出此模式。
router-view
<router-view> 用于渲染匹配的组件,基于Vue的动态组件系统,继承了一个动态组件的特性。
传递props
<router-view> 中的HTML内容被插入到相应的组件中
v-ref 父子组件通信
被渲染的组件会注册到父级组件的
this.$
对象中。
视图部分用来展示匹配路由的模板内容,在vue-router中使用router-view
来渲染匹配的组件。 router-view 是一个Vue 组件。
特性:
通过props来传递数据
支持
v-transition
和transitin-mode
.
<!-- 可以使用 transiton指令在路由切换时提供过渡效果 -->
<router-view transiton="demo" transition-mode="out-in"></router-view>
支持
v-ref
,被渲染的组件会注册到父级组件的this.$
对象中支持
solt
,router-view中的HTML内容会被插入到相应的路由组件模板的slot中。
v-link
v-link 是用户操作的时候,来匹配不同的路径。 用户点击的时候, 会调用 router.go()
<!-- 字面量路径 -->
<a v-link="'home'">Home</a>
<!-- 字面量路径 -->
<a v-link="{ path: 'home' }">Home</a>
<!-- 具名路径 -->
<a v-link="{ name: 'user', params: { userId: 111 }}">用户名</a>
v-link
会自动设置 <a>
的 href
属性
参数:
V-link
是一个Vue指令,它的值是一个JavaScript表达式,可以接受一个表示path的字符串或者包含name或path属性的对象。
如果属性值既不是字符串也不是对象字面量,则会被当作对应组件的数据属性来解析。
<!-- 字面量路径,表示path。足以:需要用单引号吧字符串内容括起来 -->
<a v-link="'/home'">HOME</a>
<!-- 值为对应组件的数据属性 -->
Vue.component('app', {
data: {
homeLinkMap: {
path: '/home'
}
}
});
当v-link
解析后的值是对象时,该对象可以有属性有:
-
params(对象)
包含路由中的动态片段和全匹配片段的键值对。
-
query(对象)
包含路由中的添加到路劲path后的键值对。
<a v-link="{path: '/home', query: {isAuthed: true}}">Home</a>
当该path被匹配是,地址栏的URL为:/home?isAuthed=true
-
replace(布尔值)
默认值为false,当该值为true时,此次导航不会产生历史记录。当用户点击的时候,会触发 `router.replace()`函数,而不是默认的 `router.go()`。作用:产生的跳转不会留下历史记录 <a v-link="{ path: '/abc', replace: true }"></a>
-
append(布尔值)
默认值false。当该值为true时,如果此次导航的目的path为相对路径,则实际URL中的路径是当前path后拼接目的path。
例如:当前path为
/a
,
<!-- 不加append属性(默认值为false),目的URL路径为 /b -->
<a v-link="{ path: 'b' }">b</a>
<!-- append为true,目的URL路径为 /a/b -->
<a v-link="{path: 'b', append: true}">/a/b</a>
activeClass(字符串)
默认值为v-link-active,值担忧v-link指令的a元素处于激活状态是的class名称。该值也可以在创建路由器实例通过选项的 linkActiveClass 属性来进行全局设置。-
path 设置字面量路径
<a v-link="{ path: 'home' }">Home</a>
-
name和params 具名路径
<a v-link="{ name: 'user', params: { userId: 111 }}">用户名</a>
-
exact 匹配是否完全一致
<a v-link="{ path: '/a', exact: true }"></a>
注意:使用 v-link而不是href来设置URL。
原因:
v-link是Vue指令,它会根据它的值来设置href的值。
在hash模式和 HTML5 history模式下,vue-router会同意行为,这样在改变模式时不需要做任何改变。
在HTML5 history模式下,v-link执行会监听点击事件,防止浏览器重新加载页面。
在HTML5 history模式下,如果使用root选项,不需要在v-link的path中包含root路径。
在Vue1.0绑定语法中,不支持Mustache插值标签,可以好似用常规的JavaScript表达式代替,例如:v-link="'user'/+user.name".
router-API
用来提供启动,路由映射,重定向,路由切换全局钩子。
start
router.start(App, el);
启动一个路由程序,创建一个App的实例并挂载到元素el上。
参数:
App(函数/对象)
App可以是一个Vue组件构造器或者组件选项对象,当为组建选项对象时,在vue-rotuer内部会调用Vue.extend来创建App构造器。
el(字符串/DOM元素)
el可以是一个CSS选择器或者DOM元素,用来挂载路由应用的跟组件。
stop
router.stop();
停止监听 popstate
和 hashchange
事件
当路由处于停止状态, router.app
并没有销毁, 依然 可以使用 router.go(path) 进行跳转。也可以不使用参数调用 router.start() 来重新启动路由。
map
router.map(routerMap);
批量定义路由映射规则,内部调用router.on
方法实现。
参数routerMap对象爱过你,键为路径,值为路由配置对象。在vue-router内部会对routerMap对象中的每个键值调用router.on();方法来进行路由映射,
路由配置对象字段componet
,当路径匹配时,会渲染到顶级<router-view>的Vue组件。
值可以是 Vue.extend()
后返回的构造函数, 或者Vue.component()
subRoutes
嵌套的子路由映射。 匹配成功后组件会渲染到父级组件的<router-view> 中。
on
router.on(path, config);
添加一条顶级的路由配置
参数:
path(字符串)
要匹配到路径。
config(对象)
路由配置对象
在内部实现时,router.map(path, config); 对于接收到的路由映射对象中每个键值对调用router.on();
router.on('/user/:userId', {
component: {
template: '<div> {{$route.params.userId}} </div>'
}
})
go
router.go(path);
导航到一个指定path的路由。
参数:
path(字符串、对象)
当path为字符串时,会当作普通路径来解析,如果路由是相对路径(不以'/'开头),则会以相对于当前路径的方式进行解析。
当path为对象时,对象中只包含path属性:
{ path: '/a/b' }
或者
{
name: 'order',
parmas: {id: 1},
query: {fieldName: 'address'}
}
当path为对象时,两种格式都可支持可选的 replace
和 append
属性:
replace 布尔类型,默认值为false。当该值为true,跳转不产生新的历史记录。
append 布尔类型,默认值为false。 当该值为true,假如要跳转的路径是相对路径,则实际路径是当前路劲拼接要跳转的录几个。假设当前路径为/a
,目的路径为b
,当append值为false时,则实际跳转后路径为/b
,为true时,则实际跳转后路径为/a/b
.
replace
router.replace(path);
导航一个新路由,但不会在浏览器创建新的历史记录.
redirect
router.redirect(redirectMap);
路由重定向
定义全局重定向规则。如果要访问的路径匹配重定向规则,则路径会重定向到指定的路径,以重定向后的路径在浏览器中生成历史记录,原本访问的路径不会生成历史记录.
redirectMap: 对象。
该参数格式为:{fromPath: toPath}
,即当前访问的路径到实例路径的映射关系。
router.redirect({
// 重定向任意未匹配到的路径
'*': '/home'
});
alias
router.alias(aliasMap);
路由别名
别名和重定向的区别:
重定向把/a
替换成 '/b',
别名会保留'/a',但是匹配时使用 '/b'
router.alias({
// 匹配 /a 时 就想是匹配 /a/b/c
'/a': 'a/b/c'
});
切换控制流水线
钩子函数:处理或过滤事件,消息的回调函数。
钩子的本质是一段用以处理消息系统的程序。
当消息到达后处理,在目标函数之前处理它。(钩子函数先得到控制权)可以加工处理(改变)该消息,也可以不做处理而继续传递该消息,还可以强制结束消息的传递。
根据钩子函数的特性,可以终止界面的切换(组件切换,组件更新,数据更新)。 每个切换钩子函数都会接受一个 transition
对象作为参数。
如果在验证阶段终止了界面切换,路由会保持当前应用状态,恢复到前一个路由。
组件的更新(数据)会等到所有受影响的组件deactivate
和 activate
钩子函数执行之后才会进行
前置钩子函数
router.beforeEach(hook)
特性:
调用发生时间: 整个切换流水线(整个路由切换)的最前端被调用
决定流水线是否启动: 如果此钩子函数拒绝了切换组件,整个切换流水线根本不会启动。
个数: 可以注册多个全局的前置钩子函数。这些函数会按照注册的顺序被调用。调用时异步的,后一个函数会等待前一个函数完成后执行。
router.beforeEach(function ( transition ) {
console.log( transition.to );
if ( transition.to.path == '/forbidden' ) {
transition.abort();
} else {
transition.next();
}
});
后置钩子函数
router.afterEach(hook);
调用时间:路由切换成功进入激活阶段
个数: 可以注册多个全局的后置钩子函数。这些函数将会按照注册的顺序被同步调用。
该钩子会在每次canDeactivete
和canActivate
钩子被resolve之后执行,并不能保证activate
钩子被resolve.
可以注册多个全局后置钩子,这些钩子会按照注册顺序调用。但和全局前置钩子不同的是,后一个钩子并不会等前一个钩子执行完才执行,它们是并行执行的。
切换过程中的钩子对象
属性:
transition.to // 要切换的路径(目标路径)的路由对象;
transition.from // 当前路径的路由对象;
方法:
transition.next(); // 处理切换过程的下一步
transition.abort([reason]); // 终止或者拒绝此次切换
transition.redirect(path); // 取消当前切换并重定向到另一个路由
data钩子函数不管组件是否可以重用,在每次路由切换的时候都会触发。
// 组件
var Home = Vue.extend({
template: '<h1>HOME</h1>',
route: {
activate: function ( transition ) {
console.log( transition.to ); // 切换的路径(目标路径)的路由对象
console.log( transition.from ); // 当前路径的路由对象
transition.next();
transition.abort();
transition.redirect();
},
deactivate: function ( transition ) {
transition.next(); // 处理切换过程的下一步
},
data: function ( transition ) { // 不管组件是否重用,每次切换路由的时候都会被调用
setTimeout(function () {
transition.next({
msg: 'data'
});
}, 1000);
}
}
});
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。