part5 - 模块2 - 02- Vue Router(路由)

236 阅读5分钟

笔记来源:拉勾教育 - 大前端就业集训营

文章内容:学习过程中的笔记、感悟、和经验

Vue Router - 路由

是Vue的官方插件,用来快速实现单页应用

单页应用程序 - SPA

单页应用:网站的 “所有” (很多)功能,都呈现在单个页面中,例如:后台管理系统、移动端、小程序都适合使用单页应用开发

优点

  • 前后端分离开发,提高开发效率
  • 业务场景切换,局部更新结构
  • 用户体验好,接近本地应用

缺点

  • 不利于SEO
  • 初次首屏加载较慢
  • 页面复杂度较高

前端路由

指的是Url内容之间的映射关系,下面是前端路由的两种实现方式

Hash方式

通过监听hashchange事件监听hash(Url的组成部分)变化,并进行页面内容更新的方式

修改hash既能更改url又不会引发页面跳转,特点就是Url中会存在一个#

<body>
  <!-- 挂载元素 -->
  <div id="app">
    <!-- 三个a标签用来点击切换hash -->
    <a href="#/">./</a>
    <a href="#/one">./one</a>
    <a href="#/tow">./tow</a>
    <!-- p标签绑定str -->
    <p id="me">还没点击</p>
  </div>
  <script>
    window.onhashchange = function () {
      // 过滤hash并却掉#
      const hash = location.hash.replace('#', '')
      // 创建字符串
      let str = ''
      // 把hash带入循环,根据值的不同修改str
      switch (hash) {
        case '/':
          str = '我点击了./'
          break;
        case '/one':
          str = '我点击了./one'
          break;
        case '/tow':
          str = '我点击了./tow'
          break;
      }
      // 把str设置给p标签
      document.getElementById('me').innerText = str
    }
  </script>
</body>

<!-- 这里只演示hash变化可以更改内容,只演示功能 -->

封装上面的方法

<body>
  <!-- 挂载元素 -->
  <div id="app">
    <!-- 三个a标签用来点击切换hash -->
    <a href="#/">./</a>
    <a href="#/one">./one</a>
    <a href="#/tow">./tow</a>
    <!-- p标签绑定str -->
    <p id="me">还没点击</p>
  </div>
  <script>
    // 创建对象封装路由功能
    const router = {
      // 路由存储位置:用来存储 url-hash 和处理函数的对应关系
      routes: {},
      // 用于添加路由规则
      route: function (path, callback) {
        // 把hash和callback的对应关系存在routes里面,即每一个hash的数值都对应着一个处理函数
        this.routes[path] = callback
      },
      // 初始化对象方法
      init: function () {
        // 获取当前对象存储起来
        const that = this
        // 创建监听hash变化
        window.onhashchange = function () {
          // 获取处理url的hash 并却掉#
          const hash = location.hash.replace('#', '')
          // 判断routes里面是否有这个hash值,如果有调用相应函数
          that.routes[hash] && that.routes[hash]()
        }
        console.log('开启监听')
      }
    }

    // 初始化路由
    router.init()

    // 获取标签元素
    const me = document.getElementById('me')

    // 添加路由规则
    router.route('/', function () {
      me.innerText = '我点击了./'
    })
    router.route('/one', function () {
      me.innerText = '我点击了./one'
    })
    router.route('/tow', function () {
      me.innerText = '我点击了./tow'
    })
    console.log(router)
  </script>
</body>

hash方式特点

  • 兼容性好,传统方式
  • 地址中有#,不太美观
  • 前进后退功能比较繁琐

History方式

采用HTML5提供的新功能实现前端路由,兼容性没有上一个好

使用HTML5中提供的history.pushState()变更URL并执行相应操作

<body>
  <!-- 三个a标签 -->
  <a href="/">/</a>
  <a href="/one">one</a>
  <a href="/tow">tow</a>
  <!-- 内容展示区 -->
  <p id="me">默认内容</p>
  <script>
    // 创建路由对象
    const router = {
      // 存储路由对应规则
      routers: {},
      // 输出路由和对应函数,添加到routers
      route(path, callback) {
        this.routers[path] = callback
      },
      // 执行路由
      go(path) {
        // 使用history.pushState方法变更url
        // 第一个参数是当前路径有关的数据,暂时没有先写null
        // 第二个参数现在浏览器不支持,写null
        // 第三个参数是路由名
        history.pushState(null, null, path)
        // 判断路由是否存在规则并执行路由规则中的函数
        this.routers[path] && this.routers[path]()
      }
    }
    
    // 获取元素
    const as = document.getElementsByTagName('a')
    const me = document.getElementById('me')
    
    // 遍历全部的a标签添加click事件
    for (const a of as) {
      a.onclick = function (e) {
        // 获取点击的a标签的href内容,这里不能直接使用e.target.href,因为这样会去获取到整个url,而我们只需要href
        const href = e.target.getAttribute('href')
        // 执行路由功能跳转
        router.go(href)
        // 阻止a默认跳转
        return false
      }
    }

    // 添加路由规则
    router.route('/', function () {
      me.innerText = './的内容'
    })
    router.route('/one', function () {
      me.innerText = './one的内容'
    })
    router.route('/tow', function () {
      me.innerText = './tow的内容'
    })

    // 总结:原理上来睡,就是创建一个对象存储路由相关的功能,把每一个路由名和对应的相关函数规则一一对应,最后当我们更改路由名的时候执行相呼应的相关操作
  </script>
</body>

问题:虽然我们实现了点击路由更新数据,但是我们发现点击浏览器前进、后退按钮页面并不会根据路由发生变化

解决方法

  1. 前进后退功能,需要在更改URL的时候保存路由标记

    • // 在更改url的时候添加标记,后面可以给前进后退功能使用
        history.pushState({'path': path}, null, path)
      
  2. 通过popstate(window)事件监听前进后退操作,检测state

    • // 初始化方法
      init() {
        // 存储一下this
        const that = this
        // 监听前进后退事件popstate
        window.onpopstate = function (e) {
          console.log(e)
          // 获取标记, 标记存在e.state.path中, 先判断一下有没有, 没有使用/
          const path = e.state ? e.state.path : '/'
          // 调用路由相关的函数
          that.routers[path] && that.routers[path]()
        }
      }
      
  3. 调用初始化方法添加事件监听

    • // 执行路由初始化操作监听前进后退
          router.init()
      

完整代码

<body>
  <!-- 三个a标签 -->
  <a href="/">/</a>
  <a href="/one">one</a>
  <a href="/tow">tow</a>
  <!-- 内容展示区 -->
  <p id="me">默认内容</p>
  <script>
    // 创建路由对象
    const router = {
      // 存储路由对应规则
      routers: {},
      // 输出路由和对应函数,添加到routers
      route(path, callback) {
        this.routers[path] = callback
      },
      // 执行路由
      go(path) {
        // 使用history.pushState方法变更url
        // 第一个参数:添加path标记,把每次的路由存进来,后面前进后退可以使用
        // 第二个参数现在浏览器不支持,写null
        // 第三个参数是路由名
        history.pushState({}, null, path)
        // 判断路由是否存在规则并执行路由规则中的函数
        this.routers[path] && this.routers[path]()
      },
      // 初始化方法
      init() {
        // 存储一下this
        const that = this
        // 监听前进后退事件popstate
        window.onpopstate = function (e) {
          console.log(e)
          // 获取标记, 标记存在e.state.path中, 先判断一下有没有, 没有使用/
          const path = e.state ? e.state.path : '/'
          // 调用路由相关的函数
          that.routers[path] && that.routers[path]()
        }
      }
    }
    // 执行路由初始化操作监听前进后退
    router.init()
    // 获取元素
    const as = document.getElementsByTagName('a')
    const me = document.getElementById('me')
    // 遍历全部的a标签添加事件
    for (const a of as) {
      a.onclick = function (e) {
        // 获取点击的a标签的href内容
        const href = e.target.getAttribute('href')
        // 执行路由功能跳转
        router.go(href)
        // 阻止a默认跳转
        return false
      }
    }

    // 添加路由规则
    router.route('/', function () {
      me.innerText = './的内容'
    })
    router.route('/one', function () {
      me.innerText = './one的内容'
    })
    router.route('/tow', function () {
      me.innerText = './tow的内容'
    })

    // 总结:原理上来睡,就是创建一个对象存储路由相关的功能,把每一个路由名和对应的相关函数规则一一对应,最后当我们更改路由名的时候执行相呼应的相关操作
  </script>
</body>

特点

  • 兼容性较差 - ie10+支持,但是往后会被普及开来,刷新可能会出现一些问题
  • 书写简便,格式美观,可存储数据量大

Vue router

vue官方的路由管理器,让构建单页面应用易如反掌

基本使用

**安装:**注意要先引入vue再引入Vue router

Vue router提供了一个全局VueRouter构造函数,并且提供了用于路由设置的组件<router-link><router-view>

  • router-link:用于切换的连接,功能类似于之前的a标签,默认是a标签,可以通过tag设置为其他标签
  • router-view:路由切换之后要进行内容切换的区域,使用router-view设置,用来显示路由匹配到的组件
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <!-- 引入vue和vue router -->
  <script src="./js/vue.js"></script>
  <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>

<body>
  <div id="app">
    <!-- router点击列表,这里可以使用tag修改默认组件标签 -->
    <router-link to="/" tag="button">index</router-link>
    <router-link to="/one">one</router-link>
    <router-link to="/tow">tow</router-link>
    <!-- router视图部分,用于展示router-link对应组件 -->
    <router-view></router-view>
  </div>
  <script>
    // 创建三个组件,这三个组件不需要添加到vue实例router就可以使用
    const index = {
        template: `<div>index的内容</div>`
      },
      one = {
        template: `<div>one的内容</div>`
      },
      tow = {
        template: `<div>tow的内容</div>`
      }

    // 创建VueRouter实例
    const router = new VueRouter({
      // VueRouter组件对应规则
      routes: [{
          path: '/', // 路由
          component: index //路由对应组件
        },
        {
          path: '/one',
          component: one
        },
        {
          path: '/tow',
          component: tow
        }
      ]
    })
    // vue实例
    const vm = new Vue({
      el: '#app',
      // 把router注入vue实例,这里采用es6语法
      router
    })
    // 注意:如果我们不注入router则vue中就没有router相关方法,注入后打印vue就可以看到router,
  </script>
</body>

步骤解析,以下步骤不分先后

  • 顶部vue挂载对象内部书写router-link和router-view
  • 创建需要使用的组件,组件可以不引入vue也可以使用
  • 创建vue-router实例,在实例中的touters中创建路由和组件的对应规则
  • 创建vue实例,将router实例注入实例中

命名视图

如果希望导航后,同时显示多个视图组件(router-view),这时就需要进行命名视图设置

注意当多个router-view存在的时候,只能有一个没有name属性,默认名称default

<body>
  <div id="app">
    <!-- 路由可点击列表 -->
    <router-link to="/one">one</router-link>
    <router-link to="/tow">tow</router-link>

    <!-- router视图部分!!!!!!!!!!!!!!!!! -->
    <!-- 新建一个视图,并命名为index!!!!!!!!!!!!!!!!!!!!! -->
    <router-view name="index"></router-view>
    <router-view></router-view>
  </div>
  <script>
    // 创建三个组件,这三个组件不需要添加到vue实例router就可以使用
    const index = {
        template: `<div>index的内容,我是公共组件</div>`
      },
      one = {
        template: `<div>one的内容</div>`
      },
      tow = {
        template: `<div>tow的内容</div>`
      }

    // 创建VueRouter实例
    const router = new VueRouter({
      // VueRouter组件对应规则
      routes: [{
          path: '/one',
          // 如果想让一个路由同时设置多个视图,把components设置为对象!!!!!!!!!!!!!!!
          components: {
            // 视图name:组件名,这里都是index简写
            index,
            // 没有命名的视图默认名字是default
            default: one
          }
        },
        {
          path: '/tow',
          components: {
            index,
            default: tow
          }
        }
      ]
    })
    // vue实例
    const vm = new Vue({
      el: '#app',
      // 把router注入vue实例,这里采用es6语法
      router
    })
    // 注意:如果我们不注入router则vue中就没有router相关方法,注入后打印vue就可以看到router,
  </script>
</body>

解析:一个路由可以同时更新多个router-view视图,但要注意多个view不能同名,默认情况需那个下view默认名为default,可以使用name属性更给名字

动态路由

当我们需要将某一类URL都映射到同一个组件,就需要使用动态路由

使用方法

  • 定义路由规则的时候,将路径-path中的某一部分使用:进行标记,即可设置动态路由
  • 设置动态路由后,动态部分可以是任意内容
  • 设置动态路由后,动态部分为任意内容均跳转到同一个组件
  • :部分对应的信息成为路径参数,存储在vue实例.$route.params
<body>
  <div id="app">
    <!-- 写三个link,三个组件映射到同一个路由 -->
    <router-link to="/user/1">用户1</router-link>
    <router-link to="/user/2">用户2</router-link>
    <router-link to="/user/3">用户3</router-link>
    <!-- 视图 -->
    <router-view></router-view>
  </div>
  <script>
    // 使用的组件
    const user = {
      template: `<div>用户{{$route.params.id}}的功能</div>`
    }
    // 路由实例
    const router = new VueRouter({
      // 路由映射规则
      routes: [{
        // :id部分是动态的,会根据上面router-link进行设置
        path: '/user/:id',
        component: user
      }]
    })
    // vue实例
    const vm = new Vue({
      // 挂载元素
      el: '#app',
      // 注入路由
      router
    })
  </script>
</body>

侦听路由参数

动态路由切换时,不是组件的销毁和创建,而是不断复用组件,这样就会导致生命周期钩子函数只能执行1次,也就无法监测到路由参数变化

如果想要响应路由参数变化,可通过watch监听$route(路由规则相关信息)

// 侦听器
watch: {
  // 侦听route变化
  $route(newR, oldR) {
    // 打印路由参数
    console.log(newR.params.id)
  }
}

路由传参处理

问题:当一个组件需要再多个路由中使用的时候,就尽量不要使用$route进行数据获取

解决方案

通过路由props设置数据,并通过组件props接收,如果不设置props默认使用$route传参

<body>
  <div id="app">
    <!-- 写三个link,三个组件映射到同一个路由 -->
    <router-link to="/user/1">用户1</router-link>
    <router-link to="/user/2">用户2</router-link>
    <router-link to="/user/3">用户3</router-link>

    <!-- 视图: 视图中传入数据参数 -->
    <router-view :data="users"></router-view>
  </div>
  <script>
    // 使用的组件
    const user = {
      // id:路由规则中的动态设置名字,下面/user/:id中:后面的部分,同名!!!!!!!
      // data顶部视图传入的数据,下面使用data,根据id显示不同内容!!!!!!!!!
      props: ['id', 'data'],
      template: `
        <div>
          <p>用户{{id}}的功能</p>
          <p>{{data[id-1].content}}</p>
        </div>`
    }
    // 路由实例
    const router = new VueRouter({
      // 路由映射规则
      routes: [{
        // :id部分是动态的,会根据上面router-link进行设置
        path: '/user/:id',
        component: user,
        // 允许接收参数!!!!!!!!!!!!!
        props: true
      }]
    })
    // vue实例
    const vm = new Vue({
      // 挂载元素
      el: '#app',
      data: {
        // 传递的数据!!!!!!!!!!!!!!!!
        users: [{
          id: 1,
          content: '我是用户1内容'
        }, {
          id: 1,
          content: '我是用户2内容'
        }, {
          id: 1,
          content: '我是用户3内容'
        }]
      },
      // 注入路由
      router,
      // 侦听器
      watch: {
        // 侦听route变化
        $route(newR, oldR) {
          // 打印路由参数
          console.log(newR.params.id)
        }
      }
    })
  </script>
</body>

路由传参的其他方式

当包含多个视图的时候,需要将路由的props设置为对象

// 多个视图
const routes = [{
  path: '/user/:id',
  // 这个路由关联多个视图
  components: { default: one, bar: tow},
  // props写成数组可以分别设置是否是否需要传参
  props: {
    // 默认视图需要传参
    default: true,
    // 设置bar视图不需要传参
    bar: false
  }
}]

如果希望给props传递静态参数,可以把props里面的某个组件的选项设置为对象,呢哦不属性会被绑定到这个组件的props上

const bar = {
  //视图直接使用组件静态数据a和b
  props: [a ,b],
  template: `.........................`
}
// 多个视图
const routes = [{
  path: '/user/:id',
  components: {
    default: one,
    bar: tow
  },
  props: {
    default: true,
    // 传递静态数据,静态数据直接写成对象结构
    bar: {
      a: 'one',
      b: 'tow'
    }
  }
}]

嵌套路由

实际开发中,路由通常是由多层嵌套组合而成的,这时需要使用嵌套路由配置

利用路由映射关系的children属性设置

<!-- 路由嵌套 -->
<body>
  <!-- 挂载节点 -->
  <div id="app">
    <!-- 父亲路由 -->
    <router-link to="/user">用户</router-link>
    <!-- 父亲视图 -->
    <router-view></router-view>
  </div>
  
  <script>
    // 将全部组件书写在一个对象内部
    const data = {
      // 父亲点击后视图
      title: {
        // 内部在嵌套一层路由和视图,这里的router-view不需要命名,和上面不在同一层级
        template: `
          <div>
            <p>我是父亲路由的视图内容</p>
            <router-link to="/user/one">用户1</router-link>
            <router-link to="/user/tow">用户2</router-link>
            <router-link to="/user/three">用户3</router-link>
            <router-view></router-view>
          </div>
        `
      },
      // 全部(子路由)用户内容
      users: [
        {template: `<div>用户1内容</div>`}, 
        {template: `<div>用户2内容</div>`}, 
        {// 在用户3下面我又嵌套了一层路由
        template: `
          <div>
            <p>用户3内容</p>
            <router-link to="/user/three/info">信息</router-link>
            <router-view></router-view>
          </div>`}
      ],
      // 用户3的信息
      threeInfo: {
        template: `<div>用户3信息</div>`
      }
    }

    // 路由实例
    const router = new VueRouter({
      // 映射关系
      routes: [{
        // 父路由信息
        path: '/user',
        // 这里组件可以使用对象中的成员
        component: data.title,
        // 嵌套的子路由放在children内部,书写方式和上面一样,如果还有子路由可再向下写
        children: [
          {path: '/user/one',component: data.users[0]},
          {path: '/user/tow',component: data.users[1]},
          {path: '/user/three', component: data.users[2],
            // 用户3下面因为还有路由所以还要写children
            children: [{path: '/user/three/info',component: data.threeInfo }]}
        ]
      }]
    })
    
    // vue实例
    new Vue({
      el: '#app',
      router
    })
  </script>
</body>

一定要注意路由router-link的to属性,子路由要加上父路由的前缀

编程式导航

通过方法设置导航

  • 使用router.push()用来导航到一个新的URL
  • router-link的to属性使用绑定方式时,也可以属性对象结构
<body>
  <!-- 编程式导航 -->
  <!-- 两个按钮执行click事件触发 vm.$router.push 方法 -->
  <button onclick="vm.$router.push('/user/1000')">1000</button>
  <button onclick="vm.$router.push({path: '/user/100'})">100</button>

  <div id="app">
    <!-- 使用v-bind绑定to属性也可以实现vm.$router.push方法,和上面效果一样 -->
    <router-link :to="{path: '/user/10000'}">10000</router-link>
    <router-view></router-view>
  </div>

  <script>
    // 组件
    const user = {
        // 使用动态路由$route.params.id数据
        template: `<p>{{$route.params.id}}</p>`
      },
      // 映射关系
      routes = [{
        // 这里采用动态路由
        path: '/user/:id',
        component: user
      }],
      // 路由实例
      router = new VueRouter({
        routes
      }),
      // vue实例
      vm = new Vue({
        el: '#app',
        router
      })

    // vm.$router.push({path: "/user/10000"})
  </script>

</body>

命名路由

通过名称表示一个路由,如果路由名字过长起名字更好表达

  • 设置路由给路由添加name
  • 在push中通过name导航到这个路由,参数通过params设置
  • 也可以在router-link中使用
<body>
  <!-- 编程式导航,使用路由命名,这里直接使用重命名school!!!!!!!!!!!!! -->
  <button onclick="vm.$router.push({name: 'school', params:{id : 1, a: '我是1'}})">1</button>
  <button onclick="vm.$router.push({name: 'school', params:{id : 2, a: '我是2'}})">2</button>
  <div id="app">
    <router-link :to="{name: 'school', params:{id : 3, a: '我是3'}}">点击</router-link>
    <router-view></router-view>
  </div>

  <script>
    // 组件
    const user = {
        // 这路可以使用导入的数据,很方便!!!!!!!!!!!!1
        template: `<p>{{$route.params.a}}</p>`
      },
      // 映射关系
      routes = [{
        // 这里采用动态路由
        path: '/user/name/:id/school',
        // 把这个路由命名为school,之后就可以直接使用名字访问
        name: 'school',
        component: user
      }],
      // 路由实例
      router = new VueRouter({
        routes
      }),
      // vue实例
      vm = new Vue({
        el: '#app',
        router
      })
  </script>

</body>

可以在组件内部访问$route.params下的所有参数

重定向

可以实现访问一个地址的时候实际上访问的是另一个路由,使用映射关系设置选项的redirect属性

<body>
  <!-- 重定向 -->
  <div id="app">
    <!-- 三个路由分别指向三个地址 -->
    <router-link to="./" tag="button">转到/</router-link>
    <router-link to="/user/5" tag="button">转到/user/5</router-link>
    <router-link to="/user" tag="button">转到/user</router-link>

    <router-view></router-view>
  </div>

  <script>
    // 组件
    const up = {
        template: `<p>这是/的内容</p>`
      },
      user = {
        template: `<p>这是/user/{{$route.params.id}}的内容</p>`
      }
    // 映射关系
    routes = [{
          path: '/',
          component: up
        },
        {
          path: '/user/:id',
          component: user
        },
        {
          path: '/user',
          // 设置重定向到 / ,当访问到 /user 的时候程序会访问 /
          redirect: '/'
        }
      ],
      // 路由实例
      router = new VueRouter({
        routes
      }),
      // vue实例
      vm = new Vue({
        el: '#app',
        router
      })
  </script>

</body>

别名

美化路由的方式,可以将比较复杂的路由地址变更为简短的地址,起到访问长地址的效果,用户访问看到的地址更加美观

但是从原理上来说,最终访问的还是长地址,只不过展示出来的是短地址

<body>
  <div id="app">
    <!-- 使用正常方式访问 -->
    <router-link :to="{name: 'my', params: {id: 10, data: 200}}">转到</router-link>
    <router-link to="/one/20/tow/three/four/five/300">转到</router-link>
    <!-- 使用别名访问,和上一个效果相同,但更简短 -->
    <router-link to="/20/300">转到</router-link>

    <router-view></router-view>
  </div>

  <script>
    // 组件
    const up = {
        template: `<p>这是{{$route.params.id}}/{{$route.params.data}}的内容</p>`
      },
      // 映射关系
      routes = [{
        path: '/one/:id/tow/three/four/five/:data',
        component: up,
        name: 'my',
        // 把id和data单独提出来建立一个别名,以后可以使用别名访问
        alias: '/:id/:data'
      }],
      // 路由实例
      router = new VueRouter({
        routes
      }),
      // vue实例
      vm = new Vue({
        el: '#app',
        router
      })
  </script>

</body>

导航守卫

可以在每次导航切换操作之前做对应操作,例如检测用户是否登陆,没有登陆跳到登陆页等等功能

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <!-- 引入vue和vue router -->
  <script src="./js/vue.js"></script>
  <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>

<body>
  <div id="app">
    <router-link to="/">首页</router-link>
    <router-link to="/user">用户</router-link>
    <router-link to="/name">名字</router-link>
    <router-view></router-view>
  </div>

  <script>
    // 组件
    const sy = {
        template: `<p>这是首页的内容</p>`
      },
      user = {
        template: `<p>这是用户的内容</p>`
      },
      name = {
        template: `<p>这是name的内容</p>`
      },
      // 映射关系
      routes = [{
          path: '/',
          component: sy
        },
        {
          path: '/user',
          component: user
        },
        {
          path: '/name',
          component: name
        },
      ],
      // 路由实例
      router = new VueRouter({
        routes
      }),
      // vue实例
      vm = new Vue({
        el: '#app',
        router
      })
    // 导航守卫
    // 参数1:切换的目标路由
    // 参数2:从哪个路由切换过来
    // 参数3:相当于回调函数,内部可以书写路由地址,注意,导航守卫功能里面必须有next执行一次(有且只能执行一次)
    router.beforeEach((to, from, next) => {
      // 打印to和ftom看一下
      console.log('from:' + from.path, 'to:' + to.path)
      // 判断我们要访问的是不是user,如果是跳转到name,如果不是继续访问
      if (to.path === '/user') {
        next('/name')
      } else {
        next()
      }
      // 注意如果不写next是不允许的,必须书写
      // 如果next内部书写false,则跳转会被阻止,同样,不写next也会被阻止
      // next(false)
    })
  </script>

</body>

</html>

histor模式

通过vue Router实例的mode选项设置,这样url会更加美观(可以去掉#),但同样需要后端支持避免出现问题

// 直接在实例内部书写
router = new VueRouter({
	mode:'history'
  routes
}),