若是你用vue-cli脚手架来搭建项目,配置过程会选择是否用到路由(详细见我上一篇简书),若是选择y,后面下载依赖会自动下载vue-router。
这里仍是说一下安装:npm install vue-router
javascript
若是在一个模块化工程中使用它,必需要经过 Vue.use() 明确地安装路由功能,用vue-cli生产了咱们的项目结构,src文件目录下会有一个router文件夹,此处就是编写路由组件的地方。在src/router/index.js,这个文件就是路由的核心文件:css
import Vue from 'vue' //引入Vue import Router from 'vue-router' //引入vue-router import Hello from '@/components/Hello' //引入根目录下的Hello.vue组件 Vue.use(Router) //Vue全局使用Router export default new Router({ routes: [ //配置路由,这里是个数组 { //每个连接都是一个对象 path: '/', //连接路径 name: 'Hello', //路由名称, component: Hello //对应的组件模板 },{ path:'/hi', component:Hi, children:[ //子路由,嵌套路由 (此处偷个懒,省得单独再列一点) {path:'/',component:Hi}, {path:'hi1',component:Hi1}, {path:'hi2',component:Hi2}, ] } ] })
1.router-link 是一个组件,它默认会被渲染成一个带有连接的a标签,经过to属性指定连接地址。
注意:被选中的router-link将自动添加一个class属性值.router-link-active。html
<router-link to="/">[text]</router-link>
2.router-view 用于渲染匹配到的组件。
①.能够给router-view组件设置transition过渡(Vue2.0 Transition常见用法全解惑)。vue
<transition name="fade"> <router-view ></router-view> </transition>
css过渡类名:
组件过渡过程当中,会有四个CSS类名进行切换,这四个类名与transition的name属性有关,好比name="fade",会有以下四个CSS类名:java
从上面四个类名能够看出,fade-enter-active和fade-leave-active在整个进入或离开过程当中都有效,因此CSS的transition属性在这两个类下进行设置。react
过渡模式mode:正则表达式
②.还能够配合<keep-alive>
使用,keep-alive能够缓存数据,这样不至于从新渲染路由组件的时候,以前那个路由组件的数据被清除了。好比对当前的路由组件a进行了一些DOM操做以后,点击进入另外一个路由组件b,再回到路由组件a的时候以前的DOM操做还保存在,若是不加keep-alive再回到路由组件a时,以前的DOM操做就没有了,得从新进行。若是你的应用里有一个购物车组件,就须要用到keep-alive。vue-router
<transition> <keep-alive> <router-view></router-view> </keep-alive> </transition>
咱们常常须要把某种模式匹配到的全部路由,全都映射到同个组件。
调用router的map方法映射路由,每条路由以key-value的形式存在,key是路径,value是组件。例如:'/home'是一条路由的key,它表示路径;{component: Home}则表示该条路由映射的组件:vue-cli
router.map({
'/home': { component: Home }, '/about': { component: About } })
例如,咱们有一个 User 组件,对于全部 ID 各不相同的用户,都要使用这个组件来渲染。那么,咱们能够在 vue-router 的路由路径中使用『动态路径参数』来达到这个效果。npm
const User = { template: '<div>User</div>' } const router = new VueRouter({ routes: [ // 动态路径参数 以冒号开头 { path: '/user/:id', component: User } ] })
例如: /user/foo 和 /user/bar 都将映射到相同的路由。
一个『路径参数』使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到this.$route.params,能够在每一个组件内使用。
你能够在一个路由中设置多段『路径参数』,对应的值都会设置到 $route.params 中。例如:
<router-link :to="{name:‘dxl’,params:{key:value}}">东西里</router-link>
$route.params.username
进行接收.上面第五点也有提到。 :冒号的形式传递参数
(1).在router路由配置文件里以冒号的形式设置参数
{ path:'/params/:newsId/:userName, component:Params }
(2).组件形式,在src/components目录下创建咱们params.vue组件。
咱们在页面里输出了url传递的参数。
<template> <div> <h2>{{ msg }}</h2> <p>新闻ID:{{ $route.params.newsId}}</p> <p>用户名:{{ $route.params.userName}}</p> </div> </template> <script> export default { name: 'params', data () { return { msg: 'params page' } } } </script>
(3).<router-view>标签path路径中传值
<router-link to="/params/888/dxl shuai>params</router-link>
(4).正则表达式在URL传值中的应用
但愿咱们传递的新闻ID只能是数字的形式,这时候咱们就须要在传递时有个基本的类型判断,path:'/params/:newsId(\\d+)/:userName'
当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。由于两个路由都渲染同个组件,比起销毁再建立,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
复用组件时,想对路由参数的变化做出响应的话:
(1). watch(监测变化) $route 对象:
const User = { template: '...', watch: { '$route' (to, from) { // 对路由变化做出响应... } } }
(2).beforeRouteUpdate 导航守卫
若是目的地和当前路由相同,只有参数发生了改变 (好比从一个用户资料到另外一个 /users/1
-> /users/2
),你须要使用 beforeRouteUpdate
来响应这个变化 (好比抓取用户信息)。
const User = { template: '...', beforeRouteUpdate (to, from, next) { // react to route changes... // don't forget to call next() } }
// 定义路由的时候以下定义,name也可为中文 const routes = [ { path: '/goods', component: goods, name: 'goods' }, { path: '/orders', component: orders, name: 'orders' }, { path: '/seller', component: seller, name: 'seller' } ]; // 建立路由实例 const router = new VueRouter({ routes: routes }) // 关键在这里,设置afterEach钩子函数 router.afterEach((to, from, next) => { document.title = to.name; })
刚进入应用都是进入到“/”这个路由的,若是想直接进入到“/goods”怎么办,有两种方法。一种是利用重定向,另外一种是利用vue-router的导航式编程。
redirect基本重定向:
const routes = [ { path: '/', redirect: '/goods'} ] 重定向的目标也能够是一个命名的路由。 const routes = [ { path: '/', redirect: { name: 'goods' }} ] 重定向时也能够传递参数 { path:'/', redirect:'/goods/:newsId(\\d+)/:userName' }
★.这里不得不提到alias别名的使用。
1.首先咱们在路由配置文件里给路径起一个别名,dxl。
{
path: '/hi', component: Hi, alias:'/dxl' }
2.配置咱们的<router-link>,起过别名以后,能够直接使用<router-link>标签里的to属性,进行从新定向。
<router-link to="/dxl">jspang</router-link>
区别:
★★★.注意一个大坑:
别名alias在path为'/'中,是不起做用的。
{
path: '/', component: Hello, alias:'/home' }
1.router.push( )
想要导航到不一样的 URL,则使用 router.push (在建立vue实例并挂载后调用)。router.push方法就是用来动态导航到不一样的连接的,这个方法会向 history 栈添加一个新的记录,因此,当用户点击浏览器后退按钮时,则回到以前的 URL。
当你点击 <router-link> 时,这个方法会在内部调用,因此说,点击 <router-link :to="..."> 等同于调用 router.push(...)。
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
2.router.replace( )
router.replace跟 router.push 很像,惟一的不一样就是,它不会向 history 添加新记录,而是跟它的方法名同样 —— 替换掉当前的 history 记录。
// 在浏览器记录中前进一步,等同于 history.forward() router.go(1) // 后退一步记录,等同于 history.back() router.go(-1)
自定义一个goback()方法,并使用this.$router.go(-1),进行后退操做
<script> export default { name: 'app', methods:{ goback(){ this.$router.go(-1); }, goHome(){ this.$router.push('/'); } } } </script>
1.路由配置文件中的钩子函数:
在路由文件中咱们只能写一个beforeEnter,就是在进入此路由配置时:
{
path:'/params/:newsId(\\d+)/:userName', component:Params, beforeEnter:(to,from,next)=>{ console.log('我进入了params模板'); console.log(to); console.log(from); next(); },
三个参数:
2.写在模板中的钩子函数:
写在模板中就能够有两个钩子函数可使用。
beforeRouteEnter:在路由进入前的钩子函数。
beforeRouteLeave:在路由离开前的钩子函数。
export default { name: 'params', data () { return { msg: 'params page' } }, beforeRouteEnter:(to,from,next)=>{ console.log("准备进入路由模板"); next(); }, beforeRouteLeave: (to, from, next) => { console.log("准备离开路由模板"); next(); } }
★此处经常使用于数据获取。
$route.params.id
获取文章数据:<template> <div class="post"> <div class="loading" v-if="loading"> Loading... </div> <div v-if="error" class="error"> {{ error }} </div> <div v-if="post" class="content"> <h2>{{ post.title }}</h2> <p>{{ post.body }}</p> </div> </div> </template> export default { data () { return { loading: false, post: null, error: null } }, created () { // 组件建立完后获取数据, // 此时 data 已经被 observed 了 this.fetchData() }, watch: { // 若是路由有变化,会再次执行该方法 '$route': 'fetchData' }, methods: { fetchData () { this.error = this.post = null this.loading = true // replace getPost with your data fetching util / API wrapper getPost(this.$route.params.id, (err, post) => { this.loading = false if (err) { this.error = err.toString() } else { this.post = post } }) } } }
export default { data () { return { post: null, error: null } }, beforeRouteEnter (to, from, next) { getPost(to.params.id, (err, post) => { next(vm => vm.setData(err, post)) }) }, // 路由改变前,组件就已经渲染完了 // 逻辑稍稍不一样 beforeRouteUpdate (to, from, next) { this.post = null getPost(to.params.id, (err, post) => { this.setData(err, post) next() }) }, methods: { setData (err, post) { if (err) { this.error = err.toString() } else { this.post = post } } } }
vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,因而当 URL 改变时,页面不会从新加载。
若是不想要很丑的 hash,咱们能够用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须从新加载页面。
const router = new VueRouter({ mode: 'history', routes: [...] })
在学习过渡效果的时候,咱们学了mode的设置,可是在路由的属性中还有一个mode。
mode的两个值:
const router = new VueRouter({ mode: 'history', routes: [ { path: '*', component: Error} ] })
这里的path:'*'就是找不到页面时的配置,component是咱们新建的一个Error.vue的文件
(这点是直接粘贴的vue官网上的教程,此处是重点要多看多体会!)
在组件中使用 $route 会使之与其对应路由造成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。
解耦前:
id
不能直接拿出来使用
const User = { template: '<div>User {{ $route.params.id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', component: User } ] })
使用 props 将组件和路由解耦:
const User = { props: ['id'], template: '<div>User {{ id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', component: User, props: true }, // 对于包含命名视图的路由,你必须分别为每一个命名视图添加 `props` 选项: { path: '/user/:id', components: { default: User, sidebar: Sidebar }, props: { default: true, sidebar: false } } ] })
这样你即可以在任何地方使用该组件,使得该组件更易于重用和测试。
1.布尔模式
若是 props 被设置为 true,route.params 将会被设置为组件属性。
2.对象模式
若是 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用。
const router = new VueRouter({ routes: [ { path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } } ] })
3.函数模式
你能够建立一个函数返回 props。这样你即可以将参数转换成另外一种类型,将静态值与基于路由的值结合等等。
const router = new VueRouter({ routes: [ { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) } ] })
/search?q=vue
会将{query: 'vue'}
做为属性传递给 SearchUser 组件。
请尽量保持 props 函数为无状态的,由于它只会在路由发生变化时起做用。若是你须要状态来定义 props,请使用包装组件,这样 Vue 才能够对状态变化作出反应。
function dynamicPropsFn (route) { const now = new Date() return { name: (now.getFullYear() + parseInt(route.params.years)) + '!' } } const router = new VueRouter({ mode: 'history', base: __dirname, routes: [ { path: '/', component: Hello }, // No props, no nothing { path: '/hello/:name', component: Hello, props: true }, // Pass route.params to props { path: '/static', component: Hello, props: { name: 'world' }}, // static values { path: '/dynamic/:years', component: Hello, props: dynamicPropsFn }, // custom logic for mapping between route and props { path: '/attrs', component: Hello, props: { name: 'attrs' }} ] })