Vue - 路由基础

路由基础

路由含义

  • 服务器端的路由: 一个地址指向一个资源页面

  • 前端的路由:框架式开发都是单页面(SPA)应用

    • single page application 单页面应用
      • 优点:体验感好,组件化开发
      • 缺点:不利于seo,首页加载慢
    • multiple page appliction 多页面应用
      • 优点:seo友好
      • 缺点:复用不好

简单实现路由:

  • hash

    hash(#)是URL 的锚点,代表的是网页中的一个位置,单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载网页,也就是说hash 出现在 URL 中,但不会被包含在 http 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面;同时每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用”后退”按钮,就可以回到上一个位置;

  • Hash模式:通过锚点值的改变,根据不同的值,渲染指定DOM位置的不同数据。

  • 监听hashchange变化,修改动态组件的内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    <template>
    <div id="app">
    <component :newURL="cur"></component>
    </div>
    </template>

    <script>
    import index from "@/pages/index"
    import car from "@/pages/car"
    import user from "@/pages/user"
    export default {
    name: 'App',
    data() {
    return {
    cur:"index"
    }
    },
    components: {
    index,user,car
    },
    mounted() {
    let _this = this;
    window.addEventListener("hashchange",function(e){
    console.log(e)
    let url = e.newURL.split("#")[1].slice(1)
    if(url){
    _this.cur = url;
    }else{
    _this.cur = 'index'
    }
    })
    },
    }
    </script>

    <style>
    *{
    margin: 0;
    padding: 0;
    }
    </style>

vue-router

  • WebApp的链接路径管理系统, 是vue生态圈里非常重要的内容

  • 文档地址:https://router.vuejs.org/zh/

  • 使用:

    • 安装vue-router

      1
      npm i vue-router --save
    • 在src下面创建router文件夹,下面创建index.js

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      import Vue from "vue";
      import VueRouter from "vue-router";

      // Vue.use(插件名) 安装插件
      Vue.use(VueRouter);

      // 引入页面组件
      import 组件A from "@/pages/组件A"
      import 组件B from "@/pages/组件B"
      import 组件C from "@/pages/组件C"

      // 实例化一个路由对象
      let router = new VueRouter({
      routes:[
      { path:"/a",component:组件A },
      { path:"/b",component:组件B },
      { path:"/c",component:组件C },
      ]
      })

    • 在App.vue 模板里面写入router-view标签,路由地址切换之后对应的组件内容展示在这里

    • 使用router-link实现a标签。 to的值就是 路由映射配置里面的path内容

  • 在脚手架初始项目的时候就选择安装vue-router,自动设计好所有配置

404配置

  • 默认情况下,访问一个没有被定义的路由地址, 页面是不会渲染任何内容。我们可以给他指定到404页面

  • 实现

    1
    2
    3
    4
    5
    6
    7
    {
    routes:[
    { path:"*",component:404组件 }
    ]
    }


激活class

  • 需要设置激活的class, 当前的路由地址和a标签一致的时候,a标签就应该激活

  • 实现:

    1
    2
    3
    4
    5
    6
    7
    {
    linkActiveClass:'自定义class名', // 非严格模式 但是可以在某个router-link上面加上exact属性,变成严格模式
    linkExactActiveClass:'自定义class名' // 严格模式
    routes:[
    { path:"*",component:404组件 }
    ]
    }

重定向

1
2
3
4
5
{
routes:[
{ path:"/地址A",redirect:"/地址B" } // 访问地址A的时候跳转到地址B
]
}

命名路由

1
2
3
routes:[
{ path:"/地址A",component:组件A, name:"名称A" },
]
1
<router-link to="/地址A"></router-link>
1
<router-link :to="{name:'名称A'}"></router-link>

动态路由

  • 使用场景:

    • 新闻列表 到新闻详情 详情需要知道新闻id。
    • 新闻分类 到新闻列表 新闻列表需要知道新闻分类id
    • 愿望: 实现页面之间的传递参数吗
  • 使用:

    1
    2
    3
    4
    5
    {
    routes:[
    { path:"/地址A/:标识符",component:组件A },
    ]
    }
    1
    <router-link to="/地址A/数据"></router-link>
    1
    2
    // 组件A里面
    this.$route.params.标识符

    实现了两个页面之间的传参

  • 注意:

    当我们在main.js中将路由挂载到vue实例上面去之后, 所有的组件对象里面都会多两个属性,一个$router,$route

    • $router表示这个路由实例对象
    • $route 表示当前页面的路由信息
      • this.$route.params 动态路由数据
      • this.$route.name 路由名称
      • this.$route.meta 元数据
      • this.$route.query search参数
      • this.$route.matched 路径信息

如何实现页面之间传参

  • 动态路由

  • query传参

    1
    <router-link to="/地址B?key=val"></router-link>
    1
    this.$route.query.key
  • 本地存储

    • localStorage.setItem(“key”,val)
    • localStorage.getItem(“key”)

路由升级

编程式导航

  • 原生JS实现页面跳转方式:

    • a href
    • JS 编程式导航
      • location.href assign replace
      • history.back forward go
  • $router

    • push

    • replace

    • go

    • back

    • forward

嵌套路由

1
2
3
4
5
6
7
8
9
10
11
12
13
{
routes:[
{
path:"/地址A", //一级路由
component:组件A,
children:[ // 二级路由, 二级路由的组件 (组件aa,组件bb,组件cc都展示在组件A的模板里面的router-view里面,而不是顶级的router-view)
{ path:"/地址A/aa",component:组件aa },
{ path:"/地址A/bb",component:组件bb },
{ path:"/地址A/cc",component:组件cc }
]
}
]
}
1
2
// 组件A里面一定要有一个router-view
(组件aa,组件bb,组件cc都展示在组件A的模板里面的router-view里面,而不是顶级的router-view)

命名视图

  • 视图就是router-view

  • 默认情况下: 一个路由只能渲染一个组件到一个指定的位置

  • 如果我们希望访问一个路由的时候,同时渲染多个组件到不同位置,这个时候就可以使用命名视图

  • 实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    {
    routes:[
    {
    path:"/地址A", //一级路由
    components:{
    default:组件A,
    x:组件X,
    y:组件y
    },

    }
    ]
    }
    1
    2
    3
    <router-view name='default'></router-view>   默认视图,可以不要name属性
    <router-view name='x'></router-view> 组件x渲染在这
    <router-view name='y'></router-view> 组件y渲染在这

元信息

1
2
3
4
5
6
7
routes:[
{
path:"/地址",
component:"组件"
meta:{ key:val } // 元信息,表示给这个路由设置一些自定义属性
}
]
1
this.$route.meta.key    // 可以获取数据

导航守卫

什么是导航守卫

进入路由、离开路由、更新路由的时候自动执行的函数。 又称之路由钩子函数

分类

  • 全局守卫
    • 前置守卫 路由进入之前会执行的函数 beforeEach
      • 设置标题
      • 权限判断
    • 后置守卫 路由离开后执行的函数 afterEach
  • 局部守卫
    • 前置守卫
    • 更新守卫
    • 后置守卫

路由懒加载

  • 原来的路由配置文件里面都是通过import 导入所有的组件。这样做,应用开始的时候就会导入这些所有的组件,增加了负担

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import Index from "@/pages/Index"
    import About from "@/pages/About"
    import New from "@/pages/New"
    import NewInfo from "@/pages/NewInfo"
    import User from "@/pages/User"
    import UserOrder from "@/pages/UserOrder"
    import UserClass from "@/pages/UserClass"
    import UserSet from "@/pages/UserSet"
    import UserIndex from "@/pages/UserIndex"
    import NotFound from "@/pages/NotFound"
    import Adv from "@/components/Adv"
    import Login from "@/pages/Login"
  • 希望打开哪个路由地址的时候就再去加载对应的路由组件。 这就是路由懒加载

    1
    2
    3
    4
    5
    import 组件名 from "@/pages/组件名"
    {
    path:"/地址",
    component:组件名
    }
    1
    2
    3
    4
    5
    {
    path:"/地址",
    component:()=>import("@/pages/组件名")
    }