自用笔记:Vue.js通过简洁的API提供高效的数据绑定和灵活的组件系统。最近在Github上看到了不少Vue的项目,很好奇,决定尝试尝试。
TODO
[ ] history的后退配置
[ ] 路由懒加载
[ ] 滚动行为
[ ] router.beforeEach
基础
路由
使用
1 | <div id="app"> |
配置
1 | import Vue from 'vue' |
1 | new Vue({ |
动态路由匹配
在 vue-router 的路由路径中使用『动态路径参数』(dynamic segment)来达到这个效果:
路径参数
1 | { path: '/user/:username', component: User } |
响应路由参数的变化
例如从 /user/foo 导航到 user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
1 | watch: { |
高级匹配模式
vue-router 使用 path-to-regexp 作为路径匹配引擎,所以支持很多高级的匹配模式,例如:可选的动态路径参数、匹配零个或多个、一个或多个,甚至是自定义正则匹配。查看它的 文档 学习高阶的路径匹配,还有 这个例子 展示 vue-router 怎么使用这类匹配
1 | { path: '/' }, |
匹配优先级
有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高。
嵌套路由
这里的
children 配置就是像 routes 配置一样的路由配置数组,所以呢,你可以嵌套多层路由。
1 | { path: '/user/:id', component: User, |
注意:以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。
编程式的导航
router.push(location)
router.push(location, onComplete?, onAbort?)
想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。
声明式 | 编程式 |
---|---|
<router-link :to="..."> | router.push(…) |
1 | // 字符串 |
router.replace(location)
router.replace(location, onComplete?, onAbort?)
跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。
声明式 | 编程式 |
---|---|
<router-link :to="..." replace> | router.replace(…) |
router.go(n)
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。
1 | // 在浏览器记录中前进一步,等同于 history.forward() |
命名路由
通过一个名称来标识一个路由显得更方便一些
1 | /user/123 |
命名视图
有时候想同时(同级)展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar(侧导航) 和 main(主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default。
1 | <router-view class="view one"></router-view> |
重定向 和 别名
重定向
路径
1 | { path: '/a', redirect: '/b' } |
命名
1 | { path: '/a', redirect: { name: 'foo' }} |
动态返回重定向
1 | { path: '/a', redirect: to => { |
别名
别名:的功能让你可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构。
1 | { path: '/a', component: A, alias: '/b' } |
HTML5 History 模式
vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。
http://localhost:8680/#/Tap/btn/Github
1 | const router = new VueRouter({ |
/user/:id
不过这种模式要玩好,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,这就不好看了。
进阶
正如其名,vue-router 提供的导航钩子主要用来拦截导航,让它完成跳转或取消。有多种方式可以在路由导航发生时执行钩子:全局的, 单个路由独享的, 或者组件级的。
导航钩子
router.beforeEach
1 | to: Route, from: Route, next: Function |
to: Route:
即将要进入的目标 路由对象
from: Route:
当前导航正要离开的路由
next: Function:
一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next(‘/‘) 或者 next({ path: ‘/‘ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。
router.afterEach
1 | after 钩子没有 next 方法,不能改变导航: |
某个路由独享的钩子
这些钩子与全局 before 钩子的方法参数是一样的。
1 | const router = new VueRouter({ |
组件内的钩子
1 | const Foo = { |
数据获取
导航完成之后获取:
先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示『加载中』之类的指示。
导航完成之前获取:
导航完成前,在路由的 enter 钩子中获取数据,在数据获取成功后执行导航。
导航完成后获取数据
1 | <template> |
在导航完成前获取数据
我们在导航转入新的路由前获取数据。我们可以在接下来的组件的 beforeRouteEnter 钩子中获取数据,当数据获取成功后只调用 next 方法。
1 | export default { |
滚动行为
注意: 这个功能只在 HTML5 history 模式下可用。
使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。
1 | const router = new VueRouter({ |
路由懒加载
为了提高页面首屏加载时间,将相关的路由结合分割,提高页面效率。结合Vue的异步组件和Webpack的code splitting feature,轻松实现路由组件的懒加载。
1 | const Foo = resolve => { |
AMD 风格的 require
1 | const Foo = resolve => require(['./Foo.vue'], resolve) |
把组件按组分块
有时候我们想把某个路由下的所有组件都打包在同个异步 chunk 中。只需要 给 chunk 命名,提供 require.ensure 第三个参数作为 chunk 的名称:
1 | const Foo = r => require.ensure([], () => r(require('./Foo.vue')), 'group-foo') |
Webpack 将相同 chunk 下的所有异步模块打包到一个异步块里面 —— 这也意味着我们无须明确列出 require.ensure 的依赖(传空数组就行)。
webpack.config.js
1 | var webpackConfig = merge(baseWebpackConfig, { |
API文档
router-link
<router-link>
组件支持用户在具有路由功能的应用中(点击)导航。 通过 to 属性指定目标地址,默认渲染成带有正确链接的 <a>
标签,可以通过配置 tag 属性生成别的标签.。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的 CSS 类名。
也可以使用:<a v-link="{name: 'user', params: {userId: 1}">This is a user whose id is 1</a>
Props参数
to
表示目标路由的链接。当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象。
字符串
1 | <!-- 字符串 --> |
表达式
1 | <!-- 使用 v-bind 的 JS 表达式'home' --> |
replace
设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录。
1 | <router-link :to="{ path: '/abc'}" replace></router-link> |
append 相对路径
设置 append 属性后,则在当前(相对)路径前添加基路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b
1 | <router-link :to="{ path: 'relative/path'}" append></router-link> |
tag 渲染标签
有时候想要
1 | <router-link to="/foo" tag="li">foo</router-link> |
active-class
设置链接激活时使用的 CSS 类名。默认值可以通过路由的构造选项 linkActiveClass 来全局配置。
1 | <router-link active-class replace to="/Tap/btn">proImg</router-link> |
exact
“是否激活”默认类名的依据是inclusive match (全包含匹配)。 举个例子,如果当前的路径是 /a 开头的,那么 <router-link to="/a">
也会被设置 CSS 类名。
Active Links
events
声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组。
默认值: ‘click’
router-view
<router-view>
组件是一个 functional 组件,渲染路径匹配到的视图组件。<router-view>
渲染的组件还可以内嵌自己的 <router-view>
,根据嵌套路径,渲染嵌套组件。
name
1 | <router-view class="view one"></router-view> |
keep-alive
1 | <transition> |
路由信息对象
一个 route object
(路由信息对象) 表示当前激活的路由的状态信息,包含了当前 URL 解析得到的信息,还有 URL 匹配到的 route records(路由记录)。
$route Watcher
1 | watch: { |
1 | router.beforeEach((to, from, next) => { |
this.$route
$route.path 绝对路径
$route.params 路由参数
关于动态片段(如/user/:username)的键值对信息,如{username: ‘paolino’}
$route.query URL查询参数
请求参数,如/foo?user=1获取到query.user = 1
$route.hash
当前路由的 hash 值 (带 #) ,如果没有 hash 值,则为空字符串。
$route.fullPath
完成解析后的 URL,包含查询参数和 hash 的完整路径。
$route.matched
数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。
1 | const router = new VueRouter({ |
当 URL 为 /foo/bar,$route.matched 将会是一个包含从上到下的所有对象(副本)。
$route.name
当前路由的名称,如果有的话
1 | { |
Router 构造配置
routes
1 | { |
mode
1 | mode: 'history', |
hash:
使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器。
history:
依赖 HTML5 History API 和服务器配置。查看 HTML5 History 模式.
abstract:
支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。
base
应用的基路径。例如,如果整个单页应用服务在 /app/ 下,然后 base 就应该设为 “/app/“。
linkActiveClass
1 | linkActiveClass:'link-active', |
scrollBehavior
1 | const router = new VueRouter({ |
1 | const scrollBehavior = (to, from, savedPosition) => { |
方法
导航钩子
增加全局的导航钩子
router.beforeEach(guard)
router.afterEach(hook)
编程式导航
动态的导航到一个新 url
router.push(location)
router.replace(location)
router.go(n) 到达
router.back() 后退
router.forward() 前进
1 | router.getMatchedComponents(location?) |