美文网首页基础前端
学习使用 Vue 路由

学习使用 Vue 路由

作者: CondorHero | 来源:发表于2019-09-25 18:54 被阅读0次

前言:现在 Vue 的路由已经开始大规模应用在单页面应用上了。比较常见的就是路由网址中的 URL 里面的hash(#) ,这个 hash(#)来源于哪里那?没错就来自HTML 的锚点技术。大概如下原理:

HTML锚点
一图胜千言。
源代码(省略好多h6标签):
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>#的作用</title>
</head>
<body>
    <h1><a href="#title">跳转到标记一 </a></h1>
    <h6>一行车马向东疾驰,行不数里,便有数骑马迎来,驰到车前,翻身下马,高声向令狐冲致意,言语礼数,甚是恭敬。</h6>
    <h1><a id="title">我是标记一</a></h1>
    <h6>一行车马向东疾驰,行不数里,便有数骑马迎来,驰到车前,翻身下马,高声向令狐冲致意,言语礼数,甚是恭敬。</h6>
</body>
</html>

除了使用锚点技术之外,很明显无论 React 还是 Vue 的路由大量使用了 H5 里面的,window.history最常用的就包含window.pushState({},"",url)=>添加一条历史记录。window.history.reolaceState()=>替换当前URL, window.history.forward() => 浏览器的前进按钮,window.history.back() => 浏览器的后退按钮,window.history.go(number)=>浏览器前进后退几步。

一、配置一个路由

Vue 官网:https://router.vuejs.org/zh/
项目安装路由:

npm install --save vue-router

项目目录的结构:这次目录的结构做的真好看,制作方法是使用搜狗输入法的(ctr+shift+z)制表符。

┏ components
┃   ┣ HaHa.vue
┃   ┗ XiXi.vue
┣ router
┃   ┗ router.js
┣ App.vue
┣ main.js
┗ index.html

最终的路由效果:


最终的路由效果

index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue 学习</title>
</head>
<body>
    <div id="app"></div>
    <script src = "./virtual/bundle.js"></script>
</body>
</html>

main.js 里 vue-router 配置四步走

import Vue from "vue";
import App from "./App.vue";
// ①
import VueRouter from "vue-router";
import routes from "./router/router.js";

// 使用路由②
Vue.use(VueRouter);
// ③
const router = new VueRouter({
   routes
})
new Vue({
    el:"#app",
    render(h){
        return h(App);
    },
    // ④
    router
});

router.js

// 引入组件
import XiXi from "../components/XiXi.vue";
import HaHa from "../components/HaHa.vue";
// 暴露路由需要的数组
export default [
    {path : "/XiXi",component : XiXi},
    {path : "/HaHa",component : HaHa}
];

App.vue

<template>
    <div>
        <h1>路由测试</h1>
        <div class="box">
            <p>我是一个盒子组件将会在这里显示</p>
            <!-- 使用 router-link 组件来导航. -->
            <!-- 通过传入 `to` 属性指定链接. -->
            <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
            <router-link to="/HaHa">Go to HaHa</router-link>
            <router-link to="/XiXi">Go to XiXi</router-link>
            <router-link to="/">Go to home</router-link>
            <!-- 路由出口 -->
            <!-- 路由匹配到的组件将渲染在这里 -->
            <router-view></router-view>
        </div>
    </div>
</template>

<script>
    export default {
        
    }
</script>

<style scoped>
.box{
    width: 500px;
    height: 200px;
    border:20px solid #5e5ed9;
}
</style>

components 里面就是单纯的两个组件。

二、子路由

我们在子组件 HaHa 里面再放入孙子组件 Bar 。URL 变成http://127.0.0.1:8080/#/HaHa/bar

演示效果大约如下:


我们需要改动的地方有:
router.js 里面在组件 HaHa 下面加入 childrren 书写子路由。与 react 不同的是子路由 不需要在前面加上 /

// 引入组件
import XiXi from "../components/XiXi.vue";
import HaHa from "../components/HaHa.vue";
import Bar from "../components/Bar.vue";
// 暴露路由需要的数组
export default [
    {path : "/XiXi",component : XiXi},
    {
        path : "/HaHa",
        component : HaHa,
        children:[
            {path : "Bar",component:Bar}
        ]
    }
];

除此之外还需要在 HaHa.vue 组件里面放上标签<router-view></router-view>,用来显示孙子组件 Bar 。

三、两种路由跳转方式
  • 第一种 HTMl 方法
    就是我们上面使用的 <router-link to="/HaHa">Go to HaHa</router-link> 标签,这个标签的页面效果就类似HTML里面的a标签。
  • JS 方法
    <a @click="$router.push('/HaHa/bar')">Go to HaHa</a> 我们在 a 标签添加事件,因为配置过路由,$router就像vuex的$store一样可以在任何子组件使用,我们只需要调用push就能指定跳转目标。
四、使用路由进行页面布局

有时候想同时 (同级) 展示多个视图,而不是嵌套展示,就例如我们的有一个网页页面的头部是一个 Header 组件,页面底部是一个Footer 组件,页面中间左边是一个侧边栏 Slider 组件。右边是页面内容 Content 组件。而我们要求输入的网址必须为:http://127.0.0.1:8080/#/index.html

原型图如下:


首先我们要是用路由的重定向功能,让网址一打开http://127.0.0.1:8080/#/就跳转到http://127.0.0.1:8080/#/index.html。路由文件添加代码:
{ path: '/', redirect: "/index.html"}

下面来讲讲如何实现,默认已经完成基本布局HTML大致布局代码:

<div class="box">
            <!-- 网页头部 -->
            <header>我是Header组件</header>
            <!-- 网页主体 -->
            <main>
                <aside>我是Slider侧边栏组件</aside>
                <section>我是Content组件</section>
            </main>
            <!-- 网页的底部 -->
            <footer>我是Footer组件</footer>
        </div>

我们只需要把每部分单独提出来变成组件然后使用路由进行显示。

  • 命名视图法
    <header><router-view></router-view></header> 组件 router-view 不加 name 属性在路由文件里面组件将会默认填充到这里,如果写了name属性那么相应的组件会映射到相应的name标签。
    我们现在把内容给提成四个组件:App.vue 配上路由就变成了
<!-- 网页头部 -->
<header><router-view></router-view></header>
<!-- 网页主体 -->
<main>
    <aside><router-view name="Slider"></router-view></aside>
    <section><router-view name="Content"></router-view></section>
</main>
<!-- 网页的底部 -->
<footer><router-view name="Footer"></router-view></footer>

然后我们只需要改变路由文件 router.js 文件,让不同的路由视图,显示显示对应的组件,只需要采用组件组的形式:

// 引入组件
import Header from "../components/Header.vue";
import Footer from "../components/Footer.vue";
import Slider from "../components/Slider.vue";
import Content from "../components/Content.vue";
// 暴露路由需要的数组
export default [
    { path: '/', redirect: "/index.html"},
    { path: '/index.html', components:{
        default:Header,
        Footer,
        Slider,
        Content
    }}
];
五、面包屑导航
面包屑导航

左边的 Slider 组件作用使用 HTML 进行路由跳转。代码为:

<template>
    <div>
        <aside>
            <div>
                <router-link class="cur" to="/">首页</router-link>
            </div>
            <div>
                <router-link class="cur" to="/index.html/yule">娱乐</router-link>
            </div>
            <div>
                <router-link class="cur" to="/index.html/news">新闻</router-link>
            </div>
        </aside>
    </div>
</template>

<script>
    export default {
        
    }
</script>

<style scoped>
.cur{
    display:inline-block;
    margin:20px 30px;
    text-decoration: none;
    color:#666;
    font-size: 16px;
}
</style>

然后去更改路由文件router.js:

{ 
    path: '/index.html',
    components : {
        default:Header,
        Footer,
        Slider,
        Content
    },
    meta:{chinese:"首页"},
    children : [
        { path : "news" ,component : News,meta:{chinese:"新闻"}},
        { path : "yule" ,component : Yule,meta:{chinese:"娱乐"}}
    ]
}

路由元信息(meta)?
定义路由的时候可以配置 meta 字段:一个路由匹配到的所有路由记录会暴露为 $route 对象的 $route.matched 数组。因此,我们需要遍历 $route.matched 来检查路由记录中的 meta 字段。

我们增加了两个子组件,news 和 yule(娱乐)。
再回到 Content 组件里面。进行配置。

<div>
    当前所在位置:
    <router-link to="/">首页</router-link> 
    {{$router.currentRoute.matched[1] ? "→ "+$router.currentRoute.matched[1].meta.chinese : null}}
    <router-view></router-view>
</div>

猛一看可能比较懵,我们来看看 $router 身上携带了什么参数,我们直接在生命周期beforeCreate 里面打印出来$router


就一个 API 有用:currentRoute,在把currentRoute 打印出来console.log(this.$router.currentRoute);

各个参数用处大约如下:

// 路由模式
console.log(this.$router.mode);
//当前路由的路径
console.log(this.$router.currentRoute.fullPath);
console.log(this.$router.currentRoute.path);
// URL路径的查询结果index.html?name=hero后面的东西{name: "hero"}
console.log(this.$router.currentRoute.query);
// 动态参数/:id,用户输入的id格式{id: "876543"}
console.log(this.$router.currentRoute.params);
// <router-view></router-view> 上的name属性
console.log(this.$router.currentRoute.name);
// meta自定义传入的参数,可以被我们使用
console.log(this.$router.currentRoute.meta.chinese);
// matched是一个数组,里面存放着满足当前路径的所有路由组件的路径
console.log(this.$router.currentRoute.matched);

需要注意的是用到路由参数的时候,可能会失效,例如: /index.html/news 导航到 /index.html/yule,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。重要的是生命周期钩子不会再被调用。在视图中如果使用路由参数(参数是对象或数组)插入,造成结果是视图不更新,所以声明式写法必须没有引用类型。除此之外解决办法就只能使用官方推荐的方法:

使用 watch (监测变化) $router 对象:

  watch: {
    '$router' (to, from) {
      // 对路由变化作出响应...
    }
  }

或者使用生命周期的 updated 来实现。亲测可行,Vue 就是乱,官网上讲不行,结果还是的以实际为准。

六、导航守卫(路由钩子)
1. 组件内的守卫
  • beforeRouteEnter 进入组件触发
  • beforeRouteUpdate (2.2 新增) 组件复用触发
  • beforeRouteLeave 离开组件触发

接下来以 XiXi 组件为例,修改代码加入路由进入和路由离开:

<template>
    <div>
        <h1>我是嘻嘻组件</h1>
    </div>
</template>

<script>
    export default {
        // 组件内的守卫
        // 导航离开该组件的对应路由时调用
        beforeRouteLeave (to, from , next) {
            // 这个离开守卫通常用来禁止用户在还未保存修改前突然离开
            const answer = window.confirm("你确定要离开当前页面!");
            if (answer) {
                next();//确定跳转
            } else {
                next(false);//导航可以通过 next(false) 来取消
            }
        },
        beforeRouteEnter (to, from, next) {
        // 进入该组件触发
        // 不!能!获取组件实例 `this`
        // 因为当守卫执行前,组件实例还没被创建
        const answer = window.confirm("你确定进入该页面!");
            if (answer) {
                next(vm => {
                // 通过 `vm` 访问本组件的实例
                console.log(vm)
                });//确定进入
            } else {
                next(false);//不进入
            }
        }
    }
</script>

<style lang="scss" scoped>

</style>

演示结果:

组件内的守卫
最最重要的就是beforeRouteLeave(将要离开当前路由),这个离开守卫通常用来禁止用户在还未保存修改前突然离开,简书写文章时未保存,或者平时填写一些表单退出时给出提示用到的就是这个。除了进入路由和离开路由还有个特殊的路由。为此特地新建一个组件 Foo,并配置路由为:{path : "/foo/:id",component : Foo}
Foo组件的内容为:
<template>
    <div>
        <h1>被复用的组件</h1>
    </div>
</template>

<script>
    export default {
        beforeRouteUpdate (to, from, next) {
        // 在当前路由改变,但是该组件被复用时调用
        // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
        // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
        // 可以访问组件实例 `this`
        const answer = window.confirm("你确定从/foo/1 => /foo/2 !");
            if (answer) {
                next(vm => {
                // 通过 `vm` 访问本组件的实例
                console.log(vm)
                });//确定进入
            } else {
                next(false);//不进入
            }
        }
    }
</script>

<style lang="scss" scoped>

</style>

在 APP 组件在添加两个跳转按钮:

<router-link to="/foo/1">/foo/1</router-link>
<router-link to="/foo/2">/foo/2</router-link>

查看演示效果:


beforeRouteUpdate

每个守卫方法接收三个参数:

  • to: Route: 即将要进入的目标 路由对象
  • from: Route:当前导航正要离开的路由。
  • next: Function:next(): 进行管道中的下一个钩子。next(false): 中断当前的导航。next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。
2. 路由独享的守卫

可以在路由配置上直接定义 beforeEnter 守卫:此处以 HaHa 组件为例

beforeEnter: (to, from, next) => {
    // 路由独享的守卫
    const answer = window.confirm("路由独享的守卫!");
    if (answer) {
        next();//确定进入
    } else {
        next(false);//不进入
    }
}

查看演示:


路由独享的守卫
3. 全局前置守卫

当一个导航触发时,全局前置守卫按照创建顺序调用。
官网代码案例:

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})

太简单不演示了。

七、路由懒加载

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。

结合 Vue 的异步组件和 Webpack 的代码分割功能,轻松实现路由组件的懒加载。

使用的形式其实就是组件的函数化:
以前:

component:About

现在:

component: () => import('./About.vue')
八、404 路由设置

常规参数只会匹配被/分隔的 URL 片段中的字符。如果想匹配任意路径,我们可以使用通配符 (*):

{
  // 会匹配所有路径
  path: '*'
}
{
  // 会匹配以 `/user-` 开头的任意路径
  path: '/user-*'
}

当使用通配符路由时,请确保路由的顺序是正确的,也就是说含有通配符的路由应该放在最后。路由 { path: '*' } 通常用于客户端 404 错误。当使用一个通配符时,$router.currentRoute.params 内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:
例如输入错误的网址为:http://127.0.0.1:8080/#/index
$router.currentRoute.params.pathMatch 匹配输出为:/index

八、滚动行为

滚动行为:使用前端路由,当切换到新路由时,想要页面滚到自己指定位置,或者是保持原先的滚动位置,就像重新加载页面那样。

const router = new VueRouter({
   routes,
   scrollBehavior (to, from, savedPosition) {
    // return 期望滚动到哪个的位置切换滚动到
    return { x: 0, y: 1000 }
  }
});

相关文章

  • 与Vue.js的第九天

    今天学习了路由 路由 路由 路由vue-router是vue的核心组件根据不同的url访问不同页面配合单页面使用 ...

  • JAVA教程:菜鸟Vue学习笔记(五)

    菜鸟Vue学习笔记(五) 上次我们学习了Vue的组件,这次我们来学习一下路由的使用。 在Vue中,所谓的路由其实跟...

  • 好程序员教程分析Vue学习笔记之五

    好程序员教程分析Vue学习笔记五,上次我们学习了Vue的组件,这次我们来学习一下路由的使用。在Vue中,所谓的路由...

  • 2018-09-23 vue初学九(路由)

    路由 vue-router是Vue的工具库使用路由需要导入router库,和vue.js一起使用 路由的使用分为四...

  • vue-router钩子函数实现路由守卫

    接上一篇,我们一起学习了vue路由的基本使用以及动态路由、路由嵌套以及路由命名等知识,今天我们一起来学习记录vue...

  • 一起学Vue:路由(vue-router)

    前言 学习vue-router就要先了解路由是什么?前端路由的实现原理?vue-router如何使用?等等这些问题...

  • VUE路由的简单使用

    VUE中如何使用路由? 路由的基本使用 在html中 引入vue 和 vue-router 包 创建vue对象并将...

  • Vue之vue-router路由

    八、vue-router路由 目录:使用、测试 1.使用 1)说明Vue Router是Vue.js官方的路由管理...

  • 学习使用 Vue 路由

    前言:现在 Vue 的路由已经开始大规模应用在单页面应用上了。比较常见的就是路由网址中的 URL 里面的hash(...

  • Vue 基础 - 前端路由

    使用vue-router实现前端路由 安装vue-router: 配置路由文件,并在vue实例中导入: 设置视图(...

网友评论

    本文标题:学习使用 Vue 路由

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