vuejs 路由:入门实操详解

2017年10月19日 305点热度 0人点赞 0条评论

用 Vue.js + vue-router 创建单页应用,是非常简单的。使用 Vue.js ,我们已经可以通过组合组件来组成应用程序,当你要把 vue-router 添加进来,我们需要做的是,将组件(components)映射到路由(routes),然后告诉 vue-router 在哪里渲染它们。

官方文档:https://router.vuejs.org/zh-cn/

hash 和 history模式

默认hash模式

#/ 开始匹配,这种叫作哈希模式(hash)

HTML5 History 模式

/ 开始,就是我们常见的方式没有 # 符号

  1.    <a href="/">首页</a>

  2.    <a href="/work">工作</a>

我们此时使用a标签来切换比较麻烦,每次更改路由模式的时候,需要单独改a标签里面herf的链接

在vue里面提供了一个更好的方式,来解决这个问题

  1.   <router-link to="/">home主页</router-link>

  2.    <router-link to="/work">我的工作</router-link>

每次切换路由的时候,里面的内容都依靠来显示在页面上

只有页面有导航的地方,打算让组件显示在页面上,必须写这个标签

  1. <template>

  2.  <div id="app">

  3.    <router-link to="/">home主页</router-link>

  4.    <router-link to="/work">我的工作</router-link>

  5.    <router-view/> 这个标签用来显示页面内容

  6.  </div>

  7. </template>

router-link 默认解析成a标签

  1. <a href="#/" class="router-link-active">home主页</a>

  2. <a href="#/work" class="router-link-exact-active router-link-active">我的工作</a>

给导航添加激活样式

通过css里面设置

  1. .router-link-active{

  2.    background-color:red

  3. }

当我们单独设置激活样式的时候,根路由 / 永远都会匹配到样式

我们可以在标签中添加 exact 方式来解决永远都会匹配到跟路径样式问题

  1.    直接加在标签属性上

  2.    <router-link exact to="/">home主页</router-link>

我们自己来给导航添加自定义class名字

通过 设置 active-class属性值 改变默认的激活样式类

  1.    <router-link to="/work" active-class="starkwang">我的工作</router-link>

统一更改激活样式

在 router/index.js里面设置 linkExactActiveClass属性

  1. export default new Router({

  2.    // mode: 'history',

  3.    mode: 'hash',

  4.    linkExactActiveClass: 'shudong', //通过设置这个属性值,给所有的激活样式,添加统一的类

当我们统一设置后,每次激活的路由标签,都带着自己设置的这个shudong类

  1. <a href="#/work" class="shudong starkwang">我的工作</a>

使用属性 tag 统一更改路由编译后的标签名字 <a></a> -> <li></li>

默认编译的标签名字是 a

  1. <router-link to="/stark" tag="li">我的Stark</router-link>

  2. 更改完后的dom

  3. <li class="shudong router-link-active">我的Stark</li>

路由嵌套 chidren

使用方式

  1.        {

  2.            path: '/about',  // 这是一级路由

  3.            component: About,

  4.            children: [{  // 里面是嵌套路由

  5.                    path: 'blog',  //如果在这个嵌套

  6.                    name: 'blog',

  7.                    component: Blog

  8.                },

  9.                {

  10.                    path: '/info',

  11.                    name: 'info',

  12.                    component: Info

  13.                }

  14.            ]

  15.        }

如果在这个嵌套里面的 path:'' 留空,默认会显示这个组件

  1. http://localhost:8080/#/about

  2. 此时会把 这个默认留空的嵌套路由组件显示出来,也就是上面的blog 组件显示出来

如果嵌套路由里面的 path:'blog' 写具体的路由,则访问的时候必须匹配

  1. 必须是这个路由精准匹配

  2. http://localhost:8080/#/about/blog

  3. 这样才会把这个blog嵌套路由组件显示出来

/ 开头的嵌套路径会被当作根路径。

这让你充分的使用嵌套组件而无须设置嵌套的路径。

  1.            {

  2.            path: '/about',  // 这是一级路由

  3.            component: About,

  4.            children: [{  // 里面是嵌套路由

  5.                    path: 'blog',  //如果在这个嵌套

  6.                    name: 'blog',

  7.                    component: Blog

  8.                },

  9.                {

  10.                    path: '/info', // 以 / 开头的嵌套路径会被当作跟路径

  11.                    name: 'info',

  12.                    component: Info

  13.                }

  14.            ]

  15.        }

  16.    访问方式:

  17.    http://localhost:8080/#/info

如果去掉 / 此时去掉了 '/info' -> 'info'

  1.        {

  2.            path: '/about',  // 这是一级路由

  3.            component: About,

  4.            children: [{  // 里面是嵌套路由

  5.                    path: 'blog',  //如果在这个嵌套

  6.                    name: 'blog',

  7.                    component: Blog

  8.                },

  9.                {

  10.                    path: 'info', // 此时去掉了 '/info'  -> 'info'

  11.                    name: 'info',

  12.                    component: Info

  13.                }

  14.            ]

  15.        }

  16.    访问方式:

  17.    http://localhost:8080/#/about/info

你会发现,children 配置就是像 routes 配置一样的路由配置数组,所以呢,你可以嵌套多层路由。

此时,基于上面的配置,当你访问 /about/info 时,about 的出口是不会渲染任何东西,这是因为没有匹配到合适的子路由。

重定向

使用方式 path:'*'

这个 * 是匹配上面没有找到的路径,会到这里。可以直接写: component:NotFound

redirect 这是一个函数,里面有参数 to,to 打印出来是一个对象:

  1. {name: undefined, meta: {…}, path: "/aaa", hash: "", query: {…}, …}

通过 to.path 可以获取当前用户访问的路径,来写一些逻辑跳转下面是使用详细方式
  1. {

  2.    path: '*',

  3.    // component: NotFound,

  4.    redirect: (to) => {

  5.        console.log(to);

  6.        if (to.path === '/aaa') {

  7.            return '/work'

  8.        } else if (to.path === '/bbb') {

  9.            return '/info'

  10.        } else {

  11.            return '/'

  12.        }

  13.    }

  14. }

最后附上所有路由文件代码

  1. import Vue from 'vue'

  2. import Router from 'vue-router'

  3. import HelloWorld from '@/components/HelloWorld'

  4. import Work from '@/components/Work'

  5. import Stark from '@/components/Stark'

  6. Vue.use(Router)

  7. const UserProfile = { template: `<div> 我是profile 组件 </div>` };

  8. const UserPosts = { template: `<div> 我是UserPosts 组件 </div>` };

  9. const Blog = { template: `<div> 我是Blog 组件 </div>` };

  10. const Info = { template: `<div> 我是Info 组件 </div>` };

  11. const NotFound = { template: `<div>404 您访问的页面不存在 </div>` };

  12. const About = { template: `<div> 我是About组件 <router-view> </router-view> </div>` };

  13. const User = {

  14.    // template: '<div>User {{ $route.params.id }}</div>'

  15.    template: ' <div class="user"> \

  16.            <h2> User {{ $route.params.id } } </h2> \

  17.            <router-view> </router-view> \

  18.            </div>'

  19. }

  20. export default new Router({

  21.    // mode: 'history',

  22.    mode: 'hash',

  23.    linkExactActiveClass: 'shudong',

  24.    routes: [{

  25.            path: '/',

  26.            name: 'Hello',

  27.            component: HelloWorld

  28.        },

  29.        {

  30.            path: '/work',

  31.            name: 'Work',

  32.            component: Work

  33.        },

  34.        {

  35.            path: '/stark',

  36.            name: 'stark',

  37.            component: Stark

  38.        },

  39.        // { path: '/user/:id', component: User }

  40.        {

  41.            path: '/user/:id',

  42.            component: User,

  43.            children: [{

  44.                    // 当 /user/:id/profile 匹配成功,

  45.                    // UserProfile 会被渲染在 User 的 <router-view> 中

  46.                    path: 'profile',

  47.                    component: UserProfile

  48.                },

  49.                {

  50.                    // 当 /user/:id/posts 匹配成功

  51.                    // UserPosts 会被渲染在 User 的 <router-view> 中

  52.                    path: 'posts',

  53.                    component: UserPosts

  54.                }

  55.            ]

  56.        },

  57.        {

  58.            path: '/about',

  59.            component: About,

  60.            children: [{

  61.                    path: 'blog',

  62.                    name: 'blog',

  63.                    component: Blog

  64.                },

  65.                {

  66.                    path: '/info',

  67.                    name: 'info',

  68.                    component: Info

  69.                }

  70.            ]

  71.        },

  72.        {

  73.            path: '*',

  74.            // component: NotFound,

  75.            redirect: (to) => {

  76.                console.log(to);

  77.                if (to.path === '/aaa') {

  78.                    return '/work'

  79.                } else if (to.path === '/bbb') {

  80.                    return '/info'

  81.                } else {

  82.                    return '/'

  83.                }

  84.            }

  85.        }

  86.    ]

  87. })

路由传参

传一个参数
  1. 在路由里面的path:'/user/:stark'   这个冒号后面跟的字符串相当于 key

  2. 在组件里面使用 this.$route.params.stark 来获取这个value的值

  3. 访问方式:

  4. http://localhost:8080/#/user/wang

  5. wang 就是console.log(this.$route.params.stark)

  6. 在后面跟 ?号,可以 `wang` 或不写 后面的参数。如果不跟?号 ,必须写这个参数。

如果想传多个参数
  1. 在路由里面添加多个key

  2. path: '/user/:stark?/:name?

  3. 访问方式

  4. http://localhost:8080/#/user/wang/stark

  5. 打印结果 console.log(this.$route.params)

  6. {stark: "wang", name: "shudong"}

  1.  {

  2.    path: '/user/:stark?/:name?',

  3.    name: 'user',

  4.    component: User

  5. },

案例:

user 组件

  1. <template>

  2.    <div>

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

  4.        <div>

  5.                <p> 姓名:{{userInfo.username}}</p>

  6.                <p> 爱好:{{userInfo.hobby}}</p>

  7.                <p> 性别:{{userInfo.sex}}</p>

  8.        </div>

  9.    </div>

  10. </template>

  11. <script>

  12.    let data = [

  13.        {

  14.            id:1,

  15.            tip:'vip',

  16.            username:'luchang',

  17.            sex:'男',

  18.            hobby:'coding'

  19.        },

  20.        {

  21.            id:2,

  22.            tip:'vip',

  23.            username:'guomian',

  24.            sex:'男',

  25.            hobby:'女'

  26.        },

  27.        {

  28.            id:3,

  29.            tip:'common',

  30.            username:'zhangming',

  31.            sex:'男',

  32.            hobby:'bug'

  33.        },

  34.    ]

  35.    export default{

  36.        data(){

  37.            return{

  38.                userList:data,

  39.                userInfo:''

  40.            }

  41.        },

  42.        watch:{

  43.            $route(){

  44.                this.getData();

  45.            }

  46.        },

  47.        created(){

  48.            this.getData();

  49.        },

  50.        methods:{

  51.            getData(){

  52.                // let id = this.$route;

  53.                console.log(this.$route);

  54.                let id = this.$route.params.userId;

  55.                if(id){

  56.                    this.userInfo = this.userList.filter((item)=>{

  57.                        return item.id == id;

  58.                    })[0]

  59.                }

  60.                console.log(this.userInfo);

  61.                // console.log(this.$route.params.stark);

  62.            }

  63.        }

  64.    }

  65. </script>

路由

  1. import Vue from 'vue'

  2. import Router from 'vue-router'

  3. import HelloWorld from '@/components/HelloWorld'

  4. import Work from '@/components/Work'

  5. import Stark from '@/components/Stark'

  6. import User from '@/components/User'

  7. Vue.use(Router)

  8. const UserProfile = { template: `<div> 我是profile 组件 </div>` };

  9. const UserPosts = { template: `<div> 我是UserPosts 组件 </div>` };

  10. const Blog = { template: `<div> 我是Blog 组件 </div>` };

  11. const Info = { template: `<div> 我是Info 组件 </div>` };

  12. const NotFound = { template: `<div>404 您访问的页面不存在 </div>` };

  13. const About = { template: `<div> 我是About组件 <router-view> </router-view> </div>` };

  14. const Users = {

  15.    // template: '<div>User {{ $route.params.id }}</div>'

  16.    template: ' <div class="user"> \

  17.            <h2> User {{ $route.params.id } } </h2> \

  18.            <router-view> </router-view> \

  19.            </div>'

  20. }

  21. export default new Router({

  22.    // mode: 'history',

  23.    mode: 'hash',

  24.    linkExactActiveClass: 'shudong',

  25.    routes: [{

  26.            path: '/',

  27.            name: 'Hello',

  28.            component: HelloWorld

  29.        },

  30.        {

  31.            path: '/work',

  32.            name: 'Work',

  33.            component: Work

  34.        },

  35.        {

  36.            path: '/user/:userId?/:name?',

  37.            name: 'user',

  38.            component: User

  39.        },

  40.        {

  41.            path: '/stark',

  42.            name: 'stark',

  43.            component: Stark

  44.        },

  45.        // { path: '/user/:id', component: User }

  46.        {

  47.            path: '/users/:id',

  48.            component: Users,

  49.            children: [{

  50.                    // 当 /user/:id/profile 匹配成功,

  51.                    // UserProfile 会被渲染在 User 的 <router-view> 中

  52.                    path: 'profile',

  53.                    component: UserProfile

  54.                },

  55.                {

  56.                    // 当 /user/:id/posts 匹配成功

  57.                    // UserPosts 会被渲染在 User 的 <router-view> 中

  58.                    path: 'posts',

  59.                    component: UserPosts

  60.                }

  61.            ]

  62.        },

  63.        {

  64.            path: '/about',

  65.            component: About,

  66.            children: [{

  67.                    path: 'blog',

  68.                    name: 'blog',

  69.                    component: Blog

  70.                },

  71.                {

  72.                    path: '/info',

  73.                    name: 'info',

  74.                    component: Info

  75.                }

  76.            ]

  77.        },

  78.        {

  79.            path: '*',

  80.            // component: NotFound,

  81.            redirect: (to) => {

  82.                // console.log(to);

  83.                if (to.path === '/aaa') {

  84.                    return '/work'

  85.                } else if (to.path === '/bbb') {

  86.                    return '/info'

  87.                } else {

  88.                    return '/'

  89.                }

  90.            }

  91.        }

  92.    ]

  93. })


相关文章推荐


一套 Vue 的单页模板:N3-admin

从 0 到 1 搭建 webpack2 + vue2 自定义模板详细教程

一些关于使用axios的心得


欢迎关注 SegmentFault 微信公众号 :)

图片

8950vuejs 路由:入门实操详解

root

这个人很懒,什么都没留下

文章评论