###前言
Vue.js的一大特色就是构建单页面应用十分方便,既然要方便构建单页面应用那么自然少不了路由,vue-router就是vue官方提供的一个路由框架,可以去查看官方文档。
###先上例子
<!-- html部分,省略head -->
<div id="app">
<div class="content">
<router-link to="/goods">商品</router-link>
<router-link to="/ratings">评论</router-link>
<router-link to="/seller">商家</router-link>
</div>
<router-view></router-view>
</div>
<script src="path-to-vue"></script>
<script src="path-to-vue-router"></script>
// 首先定义或者引入路由的组件
// 方法一:直接定义路由组件
const goods = { template: '<p>goods</p>' };
const ratings = { template: '<p>ratings</p>' };
const seller = { template: '<p>seller</p>' };
// 方法二:import引入路由组件
import goods from 'components/goods/goods';
import ratings from 'components/ratings/ratings';
import seller from 'components/seller/seller';
// 然后定义路由(routes),components还可以是Vue.extend()创建的
const routes = [
{ path: '/goods', component: goods },
{ path: '/ratings', component: ratings },
{ path: '/seller', component: seller }
];
// 接着创建路由实例
const router = new VueRouter({
// ES6缩写语法,相当于routes:routes
routes
});
// 最后创建vue实例并挂载
const app = new Vue({
el: '#app',
router
});
// 或者
const app = new Vue({
router
}).$mount('#app')
到这里就可以用vue-router轻松搭建一个单页面应用了。一般都是使用模块化编程的形式,用.vue单文件。不知道在模块化编程里怎么加载vue-router的可以参考这个项目源码
###router-link和router-view
####router-link
router-link是一个组件,它默认会被渲染成一个带有链接的a标签,通过to属性指定链接地址。注意:被选中的router-link将自动添加一个class属性值.router-link-active
####router-link属性配置
to
这是一个必须设置的属性,否则路由无法生效。表示目标路由的链接。当被点击后,内部会立刻把 to 的值传到 router.push(),所以这值是一个字符串或是描述目标位置的对象。
<router-link to="goods"></router-link>
<router-link to="{path='goods'}"></router-link>
replace
一个布尔类型,默认为false。如果replace设置为true,那么导航不会留下history记录,点击浏览器回退按钮不会再回到这个路由。
<router-link to="goods" replace></router-link>
append
一个布尔类型,默认为false。设置 append 属性后,则在当前(相对)路径前添加基路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b
<router-link :to="{ path: 'relative/path'}" append></router-link>
tag
一个字符串。router-link默认渲染成a标签,也有方法让它渲染成其他标签,tag属性就用来设置router-link渲染成什么标签的。
<!-- 渲染成li标签 -->
<router-link to="goods" tag="li"></router-link>
active-class
一个字符串。上面说了被选中的router-link将自动添加一个class属性值.router-link-active
,这个属性就是来修改这个class值的。
###router-view
这个组件十分关键,它就是用来渲染匹配到的路由的。
可以给router-view
组件设置transition
过渡,具体用法见Vue2.0 Transition常见用法全解惑。
还可以配合<keep-alive>
使用,keep-alive
可以缓存数据,这样不至于重新渲染路由组件的时候,之前那个路由组件的数据被清除了。
比如对当前的路由组件a进行了一些DOM操作之后,点击进入另一个路由组件b,再回到路由组件a的时候之前的DOM操作还保存在,如果不加keep-alive
再回到路由组件a时,之前的DOM操作就没有了,得重新进行。如果你的应用里有一个购物车组件,就需要用到keep-alive
。
<transition>
<keep-alive>
<router-view></router-view>
</keep-alive>
</transition>
###不同路由不同页面标题
多页面应用我们可以给每一个页面都设置一个不同的标题,但是如果是单页面应用的路由呢?其实也是可以实现的,实现的方法不止一种,我之前用的是结合命名路由和导航钩子函数的方法。如下:
// 定义路由的时候如下定义,name也可为中文
const routes = [
{ path: '/goods', component: goods, name: 'goods' },
{ path: '/ratings', component: ratings, name: 'ratings' },
{ path: '/seller', component: seller, name: 'seller' }
];
// 创建路由实例
const router = new VueRouter({
routes: routes
})
// 关键在这里,设置afterEach钩子函数
router.afterEach((to, from, next) => {
document.title = to.name;
})
###命名路由
命名路由就是用一个名称来标识一个路由,在定义路由的时候设置一个name属性即可。在router-link
中也可以用路由的名字来链接到一个路由。
<router-link :to="{ name: 'seller'}">seller</router-link>
###导航钩子
主要是用来拦截导航的,想使用的参考官方文档
###怎么刚进入应用就渲染某个路由组件
刚进入应用都是进入到“/”这个路由的,如果想直接进入到“/goods”怎么办,这里提供两种方法。一种是利用重定向,另一种是利用vue-router的导航式编程。
- 重定向
const routes = [
{ path: '/', redirect: '/goods'}
]
是不是很简单呢?重定向的目标也可以是一个命名的路由。
const routes = [
{ path: '/', redirect: { name: 'goods' }}
]
- 导航式编程
####router.push(location)
利用vue-router
的导航式编程的router.push
方法也可以实现上面的需求。
该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:
// 在创建vue实例并挂载后调用
router.push('/goods')
router.push方法就是用来动态导航到不同的链接的。它会向history栈添加一个新的记录,点击<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' }})
####router.replace(location)
跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录
- 声明式
<router-link :to="..." replace>
- 编程式
router.replace(...)
####router.go(n)
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)
。例如:
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)
###路由懒加载
当打包构建应用时,Javascript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
首先,可以将异步组件定义为返回一个 Promise 的工厂函数(该函数返回的Promise应该 resolve 组件本身):
const Foo = () => Promise.resolve({ /* 组件定义对象 */ })
第二,在 webpack 2中,我们可以使用动态 import语法来定义代码分块点(split point):
import('./Foo.vue') // returns a Promise
注意:如果您使用的是 babel,你将需要添加syntax-dynamic-import插件,才能使 babel 可以正确地解析语法
结合这两者,这就是如何定义一个能够被 webpack自动代码分割的异步组件
const Foo = () => import('./Foo.vue')
在路由配置中什么都不需要改变,只需要像往常一样使用 Foo:
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})
vue-router
是不是简单好用。
最后 : vue2.0
中的$router
和 $route
的区别
router
是VueRouter的一个对象,通过Vue.use(VueRouter)
和VueRouter构造函数得到一个router的实例对象,这个对象中是一个全局的对象,他包含了所有的路由包含了许多关键的对象和属性。
举例:history对象
$router.push({path:'home'});
本质是向history栈中添加一个路由,在我们看来是 切换路由,但本质是在添加一个history记录
方法:
$router.replace({path:'home'});//替换路由,没有历史记录
route
是一个跳转的路由对象,每一个路由都会有一个route对象,是一个局部的对象,可以获取对应的name,path,params,query等