vue-router学习笔记

前言

用vue-cli进行开发已经有一段时间,vue-router也常常会用到,但之前都是按需索取,并没有系统地学习过此插件,最近系统地学习了官网上的基础部分,把官网上的例子重新写一遍,故做出此篇总结。

目录

先放一张目录图(最右级的内容只是方便我去辨别这些内容)

以下每项内容都会提供一个完整的例子,例子内容与官网提供的例子大部分是一样的,但加上了注释,而且是一个可执行的html文件。

起步

在vue中实现路由配置的方式有两种,分别是声明式编程函数式编程,两者的格式如下(官网截图)

前者是html中的标签,后者在js部分书写(note:常用写法this.$router.push(xxx))。这里简单介绍下前者,后者在下面详细介绍。

实例:

<html>

<head>
</head>

<body>
    <div id="app">
        <h1>hello world!</h1>
        <!-- router-link是一个vue-router提供的链接,链接指向一个component,在router-view中显示 -->
        <router-link to="/foo">Go to foo</router-link>
        <router-link to="/bar">Go to bar</router-link>
        <router-view></router-view>
    </div>
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue"></script> -->
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <script>
        // define the component
        const Foo = { template: '<div>foo</div>' };
        const Bar = { template: '<div>bar</div>' };

        // 定义routes,配置url及相应的component
        const routes = [
            {
                path: '/foo', component: Foo
            },
            {
                path: '/bar', component: Bar
            }
        ]

        // create the router instance and pass the 'routes' option
        const router = new VueRouter({
            routes
        })

        // inject router in id
        const app = new Vue({
            router
        }).$mount('#app') 
    </script>
</body>

</html>

效果:

路由配置的基本过程: 

  1. routes数组中应该找到元素与router-link的to属性对应起来,如果没有,点击router-link时会跳转到空页面,在项目中经常配置一个全局路由捕捉这些跳转链接,显示错误链接(404)页面。其实就是编写一个这样的页面,当路由不存在时就显示此页面。这种用法非常常见,还可衍生为登陆失败,权限控制等情况
  2. 路由配置要在routes上下功夫
  3. routes的名称不固定
  4. 实际开发中组件不会这么简单,一般是单独作为一个文件引入

动态路由匹配

背景:我们常常会遇到需要引用同一个页面,但加载不同数据的情况。如用户登陆后进入自己的主页。以csdn为例,当我们来到自己的首页时,会发现有一个me.csdn.net的共同前缀,后面加上一个/id,即https://me.csdn.net/id,进入别人的主页也是如此(有些是blog.csdn.net)这些路由拥有共同的前缀,根据后面的id识别不同的登陆用户,这就涉及到动态路由配置的概念,vue-router提供了便利的方法配置这些路由。

实例:

<html>

<head>
    <title>Vue Router</title>

</head>

<body>
    <div id="app">
        <h1>hello world!</h1>
        <!-- 拥有共同的/user前缀 -->
        <router-link to="/user/foo">Go to user foo</router-link>
        <router-link to="/user/bar">Go to user bar</router-link>
        <router-view></router-view>
    </div>
    <!-- 映入vue依赖文件 -->
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <script>
        // define the component
        const User = {
            // 通过$route.params数组获取参数,即foo或bar,并显示
            template: '<div>user {{ $route.params.page }} </div>',
            // 捕捉路由的变化
            watch: {
                $route(to, from) {
                    // react to route changes...
                    console.log('to', to);
                    console.log('from', from);
                }
            }
        };

        // define routes
        const routes = [
            {
                // 动态识别所有/user/xxx路由,渲染到user组件
                path: '/user/:page', component: User
            },
        ]

        // create the router instance and pass the 'routes' option
        const router = new VueRouter({
            routes
        })

        // inject router in id
        const app = new Vue({
            router
        }).$mount('#app') 
    </script>
</body>

</html>
  1. $route.params可以拿到路由某字段的具体值(如示例中.page 和 :page 对应),$route.query可以拿到url中?后面传递的参数具体作用百度,非常方便,常用于传递数据到后台
  2. watch对象中的$route(to, from) {xxx}函数可以捕捉到路由的变化,to是目标路由参数,from是跳转前路由参数

嵌套路由

背景:有时我们会遇到这样一个场景,在一个视图中,有某一部分的内容根据路由的变化而变化(引用不同子组件),如图(官网截图):

这里路由形式与动态路由配置相似(两者常常结合起来用),但核心的不同点是,嵌套路由引用不同组件 ,这不单是嵌套路由,也是嵌套组件的设计

实例:

<html>

<head>
    <title>Vue Router</title>

</head>

<body>
    <div id="app">
        <h1>hello world!</h1>
        <router-link to="/user/page/home">Go to user home</router-link>
        <router-link to="/user/page/foo">Go to user foo</router-link>
        <router-link to="/user/page/bar">Go to user bar</router-link>
        <router-view></router-view>
    </div>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <script>
        // define the component
        const Home = { template: '<div>home</div>' };
        const Foo = { template: '<div>foo</div>' };
        const Bar = { template: '<div>bar</div>' };
        const User = {
            template: `
            <div>
                <div>User {{ $route.params.page }}</div>
                <router-view></router-view>
            </div>`,

        };

        // define routes
        const routes = [
            {
                path: '/user/:page', component: User,
                // 在children里面配置子组件
                children: [
                    {
                        // 不要加斜杆(/)否则无效
                        path: 'home',component: Home
                    },
                    {
                        path: 'foo', component: Foo
                    },
                    {
                        path: 'bar', component: Bar
                    }
                ]
            },
        ]

        // create the router instance and pass the 'routes' option
        const router = new VueRouter({
            routes
        })

        // inject router in id
        const app = new Vue({
            router
        }).$mount('#app') 
    </script>
</body>

</html>

编程式导航

背景:编程式导航不再引用router-link和router-view,而是用router.push(xxx)代替,前者是html标签,常用于页面布局,后者是js中的函数,常用于跳转和灵活传递参数(note:常在方法中以this.$router.push({....})方式调用)各司其职

 

命名路由

背景:以上方式都是通过在router-link的to里面配置路径,其实也可以通过访问组件名的方法,访问到相应的页面

实例:

<!DOCTYPE html>
<html>

<head>
    <title>Named Routes</title>
</head>

<body>
    <div id="app">
        <h1>Name Routes Test</h1>
        <router-link to="/a">go to a</router-link>
        &nbsp;
        <router-link :to="{ name: 'b' }">go to b</router-link>
        &nbsp;
        <router-link :to="{ name: 'c', params:{ id: 333 } }">go to c</router-link>
        <router-view></router-view>
    </div>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <script>
        const comA = { template: '<div>component A</div>' };
        const comB = { template: '<div>component B</div>' };
        const comC = { template: '<div>component C id is {{ $route.params.id }}</div>' };

        const routes = [
            {
                path: '/a',
                name: 'a',
                component: comA
            },
            {
                path: '/b',
                name: 'b',
                component: comB
            },
            {
                path: '/c/:id',
                name: 'c',
                component: comC
            }
        ];

        const router = new VueRouter({
            routes
        });
        const app = new Vue({
            router
        }).$mount('#app');
    </script>
</body>

</html>

命名视图

背景:有时,在一个页面中想同时引入多个组件,此时每个组件用一个名称(name)来标识即可。此功能可用来组件自己复杂的网页。(但在vue-cli中这种用法比较少,因为脚手架天然生成views目录,组建组件的操作一般在这目录中执行)

实例:

<!DOCTYPE html>
<html>

<head>
    <title>Name Views</title>
</head>

<body>
    <div id="app">
        <h1>This is a name views test.</h1>
        <router-link to="/foo">go to the foo</router-link>
        <router-link to="/bar">go to the bar</router-link>
        <router-view></router-view>
        <router-view name="a"></router-view>
        <router-view name="b"></router-view>
    </div>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <script>
        const comA = { template: `<div> component A </div>` };
        const comB = { template: `<div> component B </div>` };
        const comC = { template: `<div> component C </div>` };
        const routes = [
            {
                path: '/foo',
                components: {
                    default: comA,
                    a: comB,
                    b: comC
                }
            },
            {
                path: '/bar',
                components: {
                    default: comB,
                    a: comC,
                    b: comA
                }
            }
        ];
        const router = new VueRouter({
            routes
        });
        const app = new Vue({
            router
        }).$mount('#app');
    </script>
</body>

</html>

重定向

背景:假设有两个路由,分别是/a和/b,重定向的意思是,每次申请到达/a,最后会重定向到/b,显示的内容当然也是/b对应的组件。

实例:

<!DOCTYPE html>
<html>

<head>
    <title>Alias Test</title>
</head>

<body>
    <div id="app">
        <h1>This is redirect test.</h1>
        <router-link to="/a">go to a</router-link>
        <router-link to="/b">go to b</router-link>
        <router-view></router-view>
    </div>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <script>
        const comA = { template: '<div>component A</div>' };
        const comB = { template: '<div>component B</div>' };
        const comC = { template: '<div>component C</div>' };
        const routes = [
            {
                path: '/a',
                // 重定向的几种写法
                // redirect: '/c'
                // redirect: { name: 'c' }
                redirect: to => { // the function receives the target route as the argument
                    console.log(to); // to 是目标路由,即对象内的 path: '/a' 
                    return '/c'  // return redirect path/location here.
                }
            },
            {
                path: '/b',
                component: comB
            },
            {
                path: '/c',
                component: comC,
                name: 'c'
            }
     
        ];
        const router = new VueRouter({
            routes
        });
        const app = new Vue({
            router
        }).$mount('#app');
    </script>
</body>

</html>

别名

背景:假设有三个链接/a,/b,/c,它们的名字不同,但他们最终到达的页面是一致的,也可理解为这三个链接都引用了相同的组件,所以它们互相是别名

实例:

<!DOCTYPE html>
<html>

<head>
    <title>Alias Test</title>
</head>

<body>
    <div id="app">
        <h1>This is a alias test.</h1>
        <router-link to="/a">go to a</router-link>
        <router-link to="/b">go to b</router-link>
        <router-view></router-view>
    </div>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <script>
        const comA = { template: '<div>component A</div>' };
        const comB = { template: '<div>component B</div>' };
        const comC = { template: '<div>component C</div>' };
        const routes = [
            {
                path: '/a',
                component: comA,
                // 在地址栏中输入/c,/d地址,最终显示的都是comA的内容
                alias: ['/c','/d']
            },
            {
                path: '/b',
                component: comB
            },
     
        ];
        const router = new VueRouter({
            routes
        });
        const app = new Vue({
            router
        }).$mount('#app');
    </script>
</body>

</html>

试着在地址栏中输入/c,/d会发现显示的内容和点击'go to a'是一致的,都是component A

体会

在学习过程中,有个比较深的体会是关于学习时间的分配,我花了大部分时间来编写官网上提供的例子,并测试这些结果,而花在阅读文档的时间相对少许多(应该说是盯着文档上的代码片段来编写例子)因为文档内容其实比较少,而且文档上提供的代码只是片段,如果不去看它提供的完整例子,很难去深入理解这些内容,而以前我就是这么干的,最终导致的结果是,代码跑通了,但如果遇到问题要花一段时间去定位,也没有完全理解这些代码,只是知道这样能用而已,而且内心隐隐会产生一种很轻微的恐惧感,因为我在使用自己并不了解的东西。当我耐着性子把这些内容跑一遍后,这种恐惧感就消失了,至少是减轻了很多。类似的代码也能看懂了。内心会有种自信的声音“以后遇到这类问题,可以独立去分析解决了”。我想只有学到了这种程度,才能算是入门了吧。从这一点上可以想到,有时内心的恐惧是进步的方向,也可以想到,有效的学习方式离不开实践,必须重视手写代码啊!单看文档学到的知识是不深刻的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值