Vue路由

作者: 指尖轻敲 | 来源:发表于2018-07-09 22:32 被阅读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 }
          ]
        }
      ]
    })
    

    相关文章

      网友评论

          本文标题:Vue路由

          本文链接:https://www.haomeiwen.com/subject/vbpzjftx.html