Vue-router

vue-router

作用:通过管理url,实现url和组件的对应和通过url进行 组件间的切换。

一个url与一个组件是有映射关系的,需要用前端路由来把映射关系一一对应起来。

单页应用

加载单个html页面,并在用户与应用程序交互时动态更新该页面。访问一个网站时,实际上脂肪纹了一个页面。当我们点击导航时并不会跳转页面以及重载页面,而是通过js执行去动态的生成一些结构,把它呈现在我们想要呈现的地方。

单页应用的好处:第一次就会把所有的css,js一次性加载进来。切换链接的时候就不用重新加载资源。

一、使用vue-router步骤:

安装模块:npm install vue-router --save(使用vue-cli就不用这一步)

引入模块

import Vue from 'vue'
import VueRouter from 'vue-router'

作为Vue的插件:Vue.use(VueRouter)

创建路由实例对象

var router = new VueRouter({

   配置参数

})                        

注入Vue选项参数

new Vue({
  router:router ; //根据ES6 , 可简写为router
})

告诉路由渲染的位置

<router-view></router-view>

举个小栗子:

step1:引入vue-router

import Vue from 'vue'
import VueRouter from 'vue-router'

step2:将vue-router作为插件

Vue.use(VueRouter)

step3:引入组件

import App from './App'
import home from '@/components/home'

step4:配置路由信息

var router = new VueRouter({
    routes:[
        {
            path:'/',
            component:home
        }
    ]
})

实际应用中,路由配置会很多,所以会把它们放在另外的文件中(router文件夹index.js文件),而不是都写在main.js里面。

step5:注入到根实例

new Vue({
    el:'#app',
    router,
    template:'<App />',
    components:{
        App
    }
})

引入文件的时候,可以在webpack.base.config里面配置后缀名,比如说要引入.css文件,就可以找到加上resolve->extensions添加.css:extensions: ['.js', '.vue', '.json', '.css']。这样引入css文件就不用谢后缀名了。另外要记住,每次更改了配置文件一定要重启

下面的内容,将围绕这个小栗子展开:

二、hash和history模式

项目中最常用history模式,但低版本也会使用hash模式。

1.http://localhost:8085/#/  哈希模式,支持所有浏览器,是默认模式。这里如果a标签不加#号就会刷新页面。

<ul class="nav">
  <li>
    <a href="#/home">home</a>
  </li>
  <li>
    <a href="#/about">about</a>
  </li>
  <li>
    <a href="#/document">document</a>
  </li>
</ul>

2.要想url中不带有#号,就采用history模式,history模式支持前进后退。

路由配置项中添加如下设置为history模式:

mode:'history'

另外,a标签会跳转,使用router-view标签来做链接。

三、router-link

功能类似a标签,不会跳转。

<router-link to='/home'>home</router-link>

1.与其他标签一样,可以动态绑定属性(index为data里的数据)

<router-link :to='index'>home</router-link>

2.可以写成对象形式,添加多个配置项...

<router-link :to='{path:"/about"}'>about</router-link>

3.不仅可以作为a标签使用,还可以生成其他标签,如让router-link标签生成的是li标签,给一个tag即可,想要什么写什么

<router-link :to='index' tag="li">
    <i class="fa fa-home"></i>
    <span>home</span>
</router-link>

4.激活状态会添加名为router-link-active的class,如图点击第二个li时三个li的class:

名字太长不好记,来取一个好记的代替它,在路由配置里添加一项,将其改成is-active:

linkActiveClass:'is-active'

5.将点击切换设置为鼠标移入时切换:

<router-link to='/document' event='mouseover'>document</router-link>

可以通过<router-view>标签来控制整体样式。想要让每个组件都是居中显示,不用再每个组件中设置样式,只要在<router-view>里写就可以了:

<router-view class="center"></router-view>

当在地址栏输入 不匹配的路径 时跳转到404页面。增强用户体验

{
    path:'*',
    component:noFound
}

也可以用重定向:

四、重定向和别名

1.重定向

{
  path:'*',
//多种方式重定向:
// 1.redirect:'/home' // 2.lredirect:{path:'/home'} // 3.redirect:{name:'Home'} //4.如下: redirect:(to)=>{ //目标路由对象,访问的路径的路由信息 if(to.path === '/123'){ return '/home' }else if(to.path === '/abc'){ return '/document' }else{ return '/about' } } }

2.别名

在地址栏输入index时,也显示home页面:

{
  path: '/home',
  name:'Home',
  component: home,
  alias:'/index'
},

3.精确匹配:exact

<router-link exact to="/" tag="li">

五、嵌套路由的使用

在about里面嵌套work,study和study并将study设为默认子路由。在 about 路由配置项的 children 里面写子路由信息:

{
    path:'/about',
    component:about,
    children:[ //子路由
        {
          path:'', //默认子路由
          name:'About',
          component:study
        },
        {
          path:'/work',
          name:'Work',
          component:work
        },
        {
          path:'/hobbit',
          name:'Hobbit',
          component:hobbit
        }
    ]
}

to可以不写全路径,而是像下面这样,使用name

<router-link exact :to="{name:'About'}" tag="li"><a>study</a></router-link>
<router-link :to="{name:'Work'}" tag="li"><a>work</a></router-link>
<router-link :to="{name:'Hobby'}" tag="li"><a>hobby</a></router-link>

六、命名视图

使一个路径对应多个组件的情况。在同级同时展示多个视图,而不是嵌套展示。

 

在document组件中同时展示slider和document两个视图

<router-view name="slider"></router-view>
<router-view></router-view>
{
      path:'/document',
      name:'Document',
      components:{
        default:document,      // 默认的,渲染到没名字的<router-view>位置
        slider:slider          //渲染到<router-view name="slider">位置
      }
},

七、滚动行为

拉动滚动条,刷新浏览器之后依旧保持在滚动位置,这是浏览器的默认行为。而如果点击前进后退,依旧想要保持在刚刚滚动位置,就要使用到滚动行为

路由实例配置项中有一个scrollBehavior,点击前进后退或切换导航触发。它有3个参数:

scrollBehavior(to,from,savePosition){ 
    console.log(to); //要进入的目标路由对象 到哪里去
    console.log(from);  //离开的路由对象  从哪里来
    console.log(savePosition);   //记录滚动条的坐标  点击前进后退时记录值
    
  if(savePosition){ return savePosition; }else{ return {x:0,y:0}; } },

也可以利用hash定位。

<template>
  <div>
    我是document
    <p id="abc">定位到这个元素</p>
  </div>
</template>
<router-link to="/document#abc" tag="li">
if(to.hash){
      return {
        selector:to.hash
      }
  }

八、动态路径参数

使用场景:匹配到的所有路由,全都映射到同一个组件。比如进入个人信息页面时,每个人进入的页面时一样的,只不过不同用户展示的数据是不一样的。

路径:/user/:userId  userId为动态路径参数,不同的用户,userid是不一样的

获取参数:路由信息对象的params

在user里包含n多个用户。当点击不同用户的时候展示不同的信息。

在user组件中遍历写出嵌套结构,userList是准备好的用户数据:

<router-link :to="'/user/' + item.id" key="index" v-for="item in userList">{{item.userName}}</router-link>

要想点击用户名就显示相应的用户信息。可以先从路径拿到id,再从id拿到用户信息。

怎么拿到id?

这里就要用到对组件的注入

通过在Vue根实例的router配置传入router实例。

$router  拿到router实例对象

$route  当前激活的路由信息对象

beforeRouteEnter()  进入组件前钩子函数

beforeRouteLeave()  离开组件前钩子函数

created(){
      console.log(this.$route)
}

在浏览器打印出的route对象:

路由信息对象

一个路由信息对象表示当前激活的路由状态信息,每次成功的导航都会产生一个新对象。

fullPatn:包含hash的完整路径

hash:当前路由的hash值

matched:当前路由嵌套路由

meta:元信息

name:当前路由的名称

params:动态路径参数就是放在这里

path:对应当前路由的路径

query:URL查询参数

 

所以this.$route.params.userId就可以拿到userId。

然后创建一个空对象userInfo,将来放置拿到的id对应的用户的信息,并遍历显示。

data(){
      return{
        userList:data,
        userInfo:{}
      }
},
<p>姓名:{{userInfo.userName}}</p>
<p>性别:{{userInfo.sex}}</p>
<p>年龄:{{userInfo.age}}</p>
<p>爱好:{{userInfo.hobby}}</p>

拿到对应的用户信息,并存在userInfo

created(){
  let id = this.$route.params.userId;
  if(id){
   this.userInfo = this.userList.filter((item)=>{
  return item.id == id
   })[0]
  }else{
  userInfo = {}
  }
}

此时就可以显示用户信息了。不过还需要监控路由信息对象,如果路由信息对象发生变化,就要执行created函数。因为在一个组件中操作,组件不会重新生成,所以钩子函数只会执行一次。

  watch:{
      $route(){
        //路径发生变化,就执行这个函数
        //就可以找到用户信息啦
        this.getData();
      }
    },
    created(){
      //渲染这个组件会调用一次这个生命周期函数
      //复用这个组价这个函数不会再次被调用了
      //地址一旦发生变化,$route会生成一个新的路由信息对象
      //一旦发生变化,我们就监控到并且执行这个函数
      this.getData();
    },
    methods:{
      getData(){
        let id = this.$route.params.userId;
        if(id){
          this.userInfo = this.userList.filter((item)=>{
            return item.id == id
          })[0]
        }else{
          userInfo = {}
        }
      }
    }

九、query字符串传参

点击Ta的分享,地址栏变成这个样子-->  localhost:8085/user/vip/1?info=share

可以这样:

    <div class="info-list" v-if="userInfo.userName" style="font-size:16px;">
      <router-link exact to="?info=follow">Ta的关注</router-link>
      <router-link exact to="?info=share">Ta分享</router-link>
    </div>

也可以使用query字符串传参

<router-link exact :to="{path:'',query:{info:'follow',a:1}}">Ta的关注</router-link>
<router-link exact :to="{path:'',query:{info:'share',a:1}}">Ta分享</router-link>

点击之后路径就会变成这样:http://localhost:8085/user/vip/1?info=follow&a=1

<router-link style="padding: 0 20px" :to="{path:'/user/'+ item.tip+'/'+item.id,query:{info:'follow'}}"  key="index" v-for="item in userList">{{item.userName}}</router-link>

默认激活follow。

 十、编程式导航

之前借助于router-link实现导航的切换,也可以借助于router的实例方法,通过编写代码来实现导航的切换,

back  回退一步

forward  前进一步

go  指定前进后退步数

push  导航到不同url,向history栈添加一个新纪录

replace  导航到不同url,替换history栈中当前记录

十一、导航钩子函数

导航发生变化时,导航钩子主要用来拦截导航,让它完成跳转或取消

执行钩子函数的位置

router全局

单个路由

组件中

钩子函数

router实例上:beforeEach,afterEach

单个路由上:beforeEnter

组件内的钩子:beforeRouterEnter,beforeRouterUpdate,beforeRouterLeave

钩子函数接收的参数

to  要进入的目标路由对象

from  正要离开导航的路由对象

next  用来决定是否进入导航或者跳转

posted @ 2017-12-07 17:52  PeriHe  阅读(487)  评论(0编辑  收藏  举报