Vue路由

2018-07-09  本文已影响11人  指尖轻敲

教程

下载引用

npm install vue-router --save-dev

如果是在模块化工程使用,需要用Vue.use()安装路由功能,然后再所有组件中就可以通过this访问。

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

Vue.use(VueRouter);

如果使用全局script标签,则直接引用即可。

<script src="/path/to/vue.js"></script>
<script src="/path/to/vue-router.js"></script>

基本使用

模板:

路由分为两个部分,router-view用来呈现对应路由显示的效果,router-link通过to属性对应每个路由去切换。

<template>
    <router-view></router-view>
    <div>
      <router-link to="/home">home</router-link>
      <router-link to="/mine">mine</router-link>
    </div>
</template>
脚本代码:
  1. 引入vue和vue-router,还有所需的组件。
  2. Vue.use()使用路由
  3. 创建一个Router实例,包含一个routes数组对应每一个路由。
  4. 把Router实例挂载到Vue实例上。
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/home'
import Mine from '@/components/mine'

Vue.use(Router)

//创建一个router管理器实例。
export default new Router({
  routes: [
    {
      path: '/',
      redirect: '/home',
      component: Home
    }
    {
      path: '/home',
      name: 'home',
      component: Home
    },
    {
      path: '/mine',
      name: 'mine',
      component: Mine
    }
  ],
  mode: "history"
})

这里用到了重定向,如果访问的是/路径,就重定向到home页。类似的还有别名属性alias。这个应该不难理解,重定向就是你访问a给你定向到b页面;别名则是你给a起了个名字叫b,不管访问的地址是a还是b都会打开a页面。

routes: [
    { path: '/a', component: A, alias: '/b' }
]
挂载到vue实例上

要把router实例挂载到vue实例上,让整个应用都有路由功能。

new Vue({
  el: '#app',
  router,
})

或者,如果没有el属性,可以手动去挂在到vue实例,

new Vue({
  router
}).$mount("#app")

这样我们可以在任何组件都可以通过this.router访问路由器,也可以通过this.route访问当前路由。

路由的两种模式

摘自博客,详情请click me

hash

Router实例中的mode属性有两种模式(hash/history),默认是hash,是根据onhashchange事件,可以在window上监听这个事件,因为hash发生变化的url都会被浏览器记录下来。

onhashchange事件对象有两个属性,一个是当前页面旧的url,一个是当前页面新的url。

window.onhashchange = function(event){
    console.log(event.oldURL, event.newURL);
}
history

但是hash模式下,路由后面就会默认加上一个#号。改成history就没有了#。前面的hashchange,你只能改变#后面的url片段,而history api则给了前端完全的自由。

history可以分为切换和修改,切换的方法如下:

history.go(-2);//后退两次
history.go(2);//前进两次
history.back(); //后退
hsitory.forward(); //前进

修改历史状态包括了pushState,replaceState两个方法,这两个方法接收三个参数:stateObj,title,url

history.pushState({color:'red'}, 'red', 'red'})
window.onpopstate = function(event){
    console.log(event.state)
    if(event.state && event.state.color === 'red'){
        document.body.style.color = 'red';
    }
}
history.back();
history.forward();

通过pushstate把页面的状态保存在state对象中,当页面的url再变回这个url时,可以通过event.state取到这个state对象,从而可以对页面状态进行还原,这里的页面状态就是页面字体颜色,其实滚动条的位置,阅读进度,组件的开关的这些页面状态都可以存储到state的里面。

history可能存在的问题就是,如果服务端没有对应的资源响应的话,用F5刷新就可能会出现404。

动态路由

很多时候我们需要根据某个参数对同一个页面进行不同的渲染。比如从列表到详情也就是这种需求,所以我们需要动态路由来匹配。

export default new Router({
  routes: [
    {
      path: '/home/:id',
      name: 'home',
      component: Home
    }
  ]
})
const Home = {
  template: "<p>home {{ $route.params.id }}</p>"
}

以上代码id参数使用冒号标记,当匹配到一个路由时,参数就会被设置到this.route.params。比如访问的路径是/home/12,那么route.params就是{id: 12}

以上这种方式获取参数虽然可以,但是会使其对应的路由形成高度耦合。我们可以通过props来传参。上面代码可以改成以下:

const Home = {
  props: ['id'],
  template: "<p>home {{ id }}</p>"
}
export default new Router({
  routes: [
    {
      path: '/home/:id',
      component: Home,
      props: true
    }
  ]
})

props为true,route.params将被设置为组件属性,从props离获取到,也可以是一个对象或者有返回值的函数。

路由传参

1. 编程式路由传参

配置路由:

{
  path: '/coustomer/tags',
  name: 'tags',
  component: Tags
}

跳转时添加params参数,

this.$router.push({ name: "tags", params: { from: "detail" } });

跳转成功后,在tags这个页面可以访问到:

console.log(this.$route.params); // {from: 'detail'}
2. 使用query传递

和使用params一样,替换成query即可,这样的传递参数会在url后面显示。在页面中也可以直接获得。

this.$route.query.from

路由嵌套

这里的<router-view>是顶层的出口,同样一个被渲染的组件也可以包含自己的路由。

<div id="app">
    <router-view></router-view>
    <div>
        <router-link to="/user/foo">/user/foo</router-link>
        <router-link to="/user/foo/profile">/user/foo/profile</router-link>
        <router-link to="/user/foo/posts">/user/foo/posts</router-link>
    </div>
</div>

我们在User组建的模板添加一个<router-view>

const User = {
  template: `
    <div class="user">
      <h2>User {{ $route.params.id }}</h2>
      <router-view></router-view>
    </div>
  `
}
const UserHome = { template: '<div>Home</div>' }
const UserProfile = { template: '<div>Profile</div>' }
const UserPosts = { template: '<div>Posts</div>' }

在VueRoyuter实例中使用children配置,为了避免访问/user/foo时页面没有渲染,我们提供一个空的路由匹配UserHome 模板。

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User,
      children: [
        // UserHome will be rendered inside User's <router-view>
        // when /user/:id is matched
        { path: '', component: UserHome },
                
        // UserProfile will be rendered inside User's <router-view>
        // when /user/:id/profile is matched
        { path: 'profile', component: UserProfile },

        // UserPosts will be rendered inside User's <router-view>
        // when /user/:id/posts is matched
        { path: 'posts', component: UserPosts }
      ]
    }
  ]
})
上一篇下一篇

猜你喜欢

热点阅读