目 录CONTENT

文章目录

Vue基础第四课

Administrator
2020-07-24 / 0 评论 / 0 点赞 / 6854 阅读 / 20925 字 / 正在检测是否收录...

Vue基础第四天

vue-router前端路由

路由的概念本是通过url地址栏动态的去显示浏览器里面的内容,我们以前学习express的时候,通过express来构建过路由。这一种路由我们叫后端的路由(服务器路由)

同理,前端也是可以有路由的,前端的路由也是根据访问地址URL发生改变以后动态的去显示页面上面的内容,它的原理率主要是基于浏览器的地址栏时面的target这一个特性,下面的例子演示了基本原理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>前端路由原理</title>
    <style type="text/css">
        #login,
        #register,
        #index {
            width: 100%;
            height: 100%;
            position: fixed;
            display: none;
        }      
        #login {
            background-color: antiquewhite;
        }        
        #index {
            background-color: blue;
        }     
        #register {
            background-color: aquamarine;
        }        
        #login:target,
        #register:target,
        #index:target {
            display: block;
        }  
        #app>div:not(:target) {
            display: none;
        }
    </style>
</head>
<body>
    <div id="app">
        <div id="login">
            这是一个登陆的页面
        </div>
        <div id="register">
            这是一个注册的页面
        </div>
        <div id="index">
            这是主页内容,里面有很多东西
        </div>
    </div>
</body>
</html>

说明:在上面的代码当中,我们分别定义了三个div,取了不同的id,然后在css当中,通过:target这一css特性,去决定要让那一个div显示出来,这就是前端路由原理

在vue当中,我们有一个第三方的插件叫vue-router,这个插件就是vue全家桶里面的一员,它主要负责将我们的组件按照不同的url地址去动态的显示或隐藏,现在,我们就来学习一下这个插件

  1. 导入vue-router包

    $ cnpm install vue-router 
    
  2. 在要使用的项目当中引入

  3. 创建Vue对象,接管页面区域

  4. 创建组件,注册到vue里面去

  5. 创建VueRouter对象,用于决定到底有几个路由,每个路由的地址与组件怎么构成关系

  6. 将创建的VueRouter加载到Vue对象时面去

现在,请参考下面代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>前端路由</title>
    <script src="./js/vue.min.js"></script>
    <script src="./js/vue-router.min.js"></script>
    <link href="./bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css">
    <style type="text/css">
        .activelink {
            font-weight: bold;
            color: red !important;
        }
    </style>
</head>

<body>
    <div id="app">
        <nav class=" navbar navbar-default" role="navigation">
            <div class=" container">
                <div class=" navbar-header">
                    <a href="#" class=" navbar-brand">Vue-Router</a>
                </div>
                <ul class=" nav navbar-nav navbar-right">
                    <li>
                        <!-- <a href="#/login">登陆</a> -->
                        <router-link :to="{name:'login'}" active-class="activelink">登陆</router-link>
                    </li>
                    <!-- 这一个地方的router-link默认情况下,会被渲染成一个a标签
                         如果你要把它渲染成其它的标签 ,那么就用tag去改变它的属性值
                    -->
                    <li>
                        <!-- <router-link to="/register">注册</router-link> -->
                        <router-link :to="{name:'reg'}" active-class="activelink">注册</router-link>
                    </li>
                </ul>
            </div>
        </nav>
        <!-- 在这里,加上一个router-view以后,那么,就会根据你的路由地址,把你的组件加载到这一个地方来-->
        <router-view></router-view>
    </div>

    <!-- 这是登陆的组件模板-->
    <template id="login">
      <div class=" container">
        <div class=" page-header">
          <h2 class=" text-center text-primary">登陆</h2>
        </div>
        <form role="form" class=" form-horizontal" style="width:600px;margin: auto">
          <div class=" form-group" >
            <div class=" input-group">
              <div class=" input-group-addon">
                账号
              </div>
              <input type="text" placeholder="请输入账号" class=" form-control">
            </div>
          </div>
          <div class=" form-group" >
            <div class=" input-group">
              <div class=" input-group-addon">
                密码
              </div>
              <input type="text" placeholder="请输入密码" class=" form-control">
            </div>
          </div>
          <div class=" form-group">
              <button type="button" class=" btn btn-primary btn-block">登陆</button>
          </div>
        </form>
      </div>
    </template>

    <!--这是注册的组件模板-->
    <template id="register">
        <div class=" container">
          <div class=" page-header">
            <h2 class=" text-center text-primary">注册</h2>
          </div>
          <form role="form" class=" form-horizontal" style="width:600px;margin: auto">
            <div class=" form-group" >
              <div class=" input-group">
                <div class=" input-group-addon">
                  账号
                </div>
                <input type="text" placeholder="请输入账号" class=" form-control">
              </div>
            </div>
            <div class=" form-group" >
              <div class=" input-group">
                <div class=" input-group-addon">
                  密码
                </div>
                <input type="text" placeholder="请输入密码" class=" form-control">
              </div>
            </div>
            <div class=" form-group text-center">
              <button type="button" class=" btn btn-primary">注册</button>
              <button type="button" class=" btn btn-info">返回</button>
            </div>
          </form>
        </div>
    </template>
</body>
<script>
    var login = {
        template: "#login"
    };
    var register = {
        template: "#register"
    };
    //现在组件已经定义好了,我需要当前这个页面根据我访问的url然后用vue动态的去加载我们的组件
    //创建一个vue的路由对象
    //router代表的是路由管理对象
    //route 代表单个当前的路由对象
    var router = new VueRouter({
        //这里的routes就是用来定义,你这里有多少个路由对象
        routes: [
            //里面的每一个路由都是一个对象
            {
                path: "/login", //代表当前url跳转的路径
                component: login, //代表在当前这个路径下面,我们如何显示组件(显示那一个组件)
                name: "login" //给当前路由取一个别名
            }, {
                path: "/register",
                component: register,
                name: "reg"
            }
        ]
    })
    new Vue({
        el: "#app",
        router,
        components: {
            login,
            register
        }
    })
</script>
</html>

说明:在上面的代码当中,我们使用了组件,也使用了VueRouter对象,还使用Vue对象,上面的代码充分按照我们之前的6个步骤来完成,有几点需要在这里说明一下

  • 创建路由我们使用VueRouter

    var router=new VueRouter({
        routes:[
    
        ]
    });
    

    在这个创建过程里面,它接收一个参数,这个参数是一个对象,里面有一个routes属性,这个routes代表的就是所有单个对象的集合

  • 创建路由的时候,创建里面的单个路由对象,里面的每个路由都是一个对象,这个对象里面,有两个必填属性,一个是path,一个是component,代表如下

    {
        path:"/login",  //代表路径
        component:login,  //代表加载的组件
        name:"login"	//代表路由的别别
    }
    
  • 在要显示路由的地方,我们使用Vue内部的组件router-view去显示<router-view></router-view>;

  • 如果希望点击某一个链接以后执行跳转路由,我们可以通过下面三种方法来完成:

    1. a标签来完成

      <a href="#/register">注册</a>
      
    2. router-link的to属性指向path

      <router-link to="/register">注册</router-link>
      
    3. router-link的to属性动态绑定

      <router-link :to="{name:'register'}">注册</router-link>
      

      说明:这里的register是路由的别名

vue-router子路由(嵌套路由)

我们的Vue是根据url地址动态的切换我们页面上面的内容,它可以在一级路由下面直接切换,也可以在某一个路由下面去切换,这样就构成一个路由的嵌套,现在我们来看一下代码

 <!-- 这是登陆的组件模板-->
<template id="login">
    <div class=" container">
        <div class=" page-header">
            <h2 class=" text-center text-primary">登陆</h2>
        </div>
        <ul class=" nav nav-pills nav-justified">
            <li>
                <router-link :to="{name:'loginByForm'}" active-class="active">账号登陆</router-link>
            </li>
            <li>
                <router-link :to="{name:'loginByqrCode'}" active-class="active">扫码登陆</router-link>
            </li>
            <!-- 根据路由地址,显示不同组件内容 -->
            <router-view></router-view>
        </ul>
    </div>
</template>

<!-- 账号登陆模板 -->
<template id="loginByForm">
    <form role="form" class=" form-horizontal" style="width:600px;margin: auto">
        <div class=" form-group" >
            <div class=" input-group">
                <div class=" input-group-addon">
                    账号
                </div>
                <input type="text" placeholder="请输入账号" class=" form-control">
            </div>
        </div>
        <div class=" form-group" >
            <div class=" input-group">
                <div class=" input-group-addon">
                    密码
                </div>
                <input type="text" placeholder="请输入密码" class=" form-control">
            </div>
        </div>
        <div class=" form-group">
            <button type="button" class=" btn btn-primary btn-block">登陆</button>
        </div>
    </form>
</template>

说明:在上面的代码里面, 我们就注册了两个模板,然后通过这两个模板去构成组件

var login = {
    template: "#login"
};
var register = {
    template: "#register"
};
var loginByForm = {
    template: "#loginByForm"
};
var loginByqrCode = {
    template: "#loginByqrCode"
};

说明:上面的代码分别构成了四个组件

我们上面的四个组件当中,我们希望把oginByForm与loginByarCode嵌入到login的路由里面,这个时候,html代码如下:

<!-- 这是登陆的组件模板-->
<template id="login">
    <div class=" container">
        <div class=" page-header">
            <h2 class=" text-center text-primary">登陆</h2>
        </div>
        <ul class=" nav nav-pills nav-justified">
            <li>
                <router-link :to="{name:'loginByForm'}" active-class="active">账号登陆</router-link>
            </li>
            <li>
                <router-link :to="{name:'loginByqrCode'}" active-class="active">扫码登陆</router-link>
            </li>
            <!-- 根据路由地址,显示不同组件内容 -->
            <router-view></router-view>
        </ul>
    </div>
</template>

说明:这个时候,我们看到,在登陆的组内部,我们又有一个router-view,这就相当于一个子级的路由

模板与组件都配置完成以后,我们需要在配置router对象,让login这个组件与loginByForm及loginByqrCode构成嵌套路由关系,这时候,路由配置如下:

var router = new VueRouter({
    //这里的routes就是用来定义,你这里有多少个路由对象
    routes: [
        //里面的每一个路由都是一个对象
        {
            path: "/login", //代表当前url跳转的路径
            component: login, //代表在当前这个路径下面,我们如何显示组件(显示那一个组件)
            name: "login", //给当前路由取一个别名
            children: [
                //里面的配置方法与routes里面的配置方法一样,只是在path的路径配置处有一些不一样
                //如果是子级路由,那么,我们就需 要注意,在path里在,不要写"/"
                //这样,它出现的路径就是在父级路由的下面去追加新路径
                {
                    name: "loginByForm",
                    component: loginByForm,
                    path: "loginByForm"
                }, {
                    name: "loginByqrCode",
                    component: loginByqrCode,
                    path: "loginByqrCode"
                }
            ]
        }, {
            path: "/register",
            component: register,
            name: "reg"
        }
    ]
})

说明:在上面的代码里面,我们看到了在login的路由下在,我们配置了一个children的属性,这一个属性代表它下面的子级路由,这个子级路由的配置与我们之前的router里面的配置大同小异,只是在path的路径这里需要特别注意一下,具体请看代码注释

router-link的相关配置

在router-link当中,它的主要作用就是用来帮我们进行页面跳转的,相当于我们的a标签,同时,我们也看到了,router-link默认情况下,会在页面当中渲染成我们的a标签

active-class

active-class代表了当前这个router-link被激活以后所使用的样式信息,默认的值为 router-link-active

如果你希望改变它的默认值 ,这个时候,只需要改变它的active-class的属性值就可以了,这个时候,当这个路由被选中激活的时候,就会应用上你的样式信息

<router-link active-class="active" to="/register">注册</router-link>

tag属性

在vue-router里面,router-link默认会被渲染成一个a标签,如果你想把它渲染成一个其它的标签,那么,就请使用tag去改变它的属性值,如下所示:

<router-link tag="span" to="/login">登陆</router-link>

说明:上面代码经过渲染以后,最终得到的标签就是span标签,它虽然被渲染成了span标签,但是,还是具备路由跳转切换的功能

路由重定向

在VueRouter里面,我们可以进行路由的转向,也就是重定向,重定向的方式多种多样,其中,最主要的有以下几种:

  1. 通过path重定向

    {
        path: "/",
        redirect: "/login/loginByForm",
    }
    

    说明:当路由的地址指向'/'的时候,它就会跳转到/login/loginByForm这个地址,'/'代表了VueRouter的默认启动地址

  2. 通过别名重定向

    {
        path: "/",
        redirect: {
            name: "loginByForm"
        }
    }
    
  3. 通用匹配

    当我们的路由地址找不到的时候,我们希望匹配一个默认的路由,这个时候就要进行如下配置

    {
        path: "*", //没有找到匹配的路由
        redirect: "/register"
    }
    

编程式路由

通过刚刚的学习,我们都知道,如果我们要跳转一个路由,我们可以使用router-link的方式进行跳转,可是这样做的局限性非常大,如果假设,我们希望通过js代码的形式进行路由跳转,这个时候,应该怎么操作呢?

为了解决这一个问题,VueRouter就推出了编程式路由,以编程的形式解决路由的跳转问题

编程式路由的跳转常用的两种方式如下:

  1. 通过path去跳转

    this.$router.push({
        path: "/login"
    }); 
    
  2. 通过name去跳转

    this.$router.push({
        name: "login"
    });
    

上面的两种方式都可以进行路由的跳转,但是它们的应用点不一样,区别主要是在路由的传值方式不一样

路由传值

在前端的路由里面,我们在切换路由的时候,也相当于切换了组件(切换了页面),页面与页面之前有时候需要做到传值 ,这个时候,在VueRouter里面,两个路由之间做跳转的时候,如何进行传值呢?

VueRouter的路由传值有两种试

  1. query传值。 这一种传值方式,我们叫做get传值

    传值的路由

    this.$router.push({
        path: "/login?uname=" + this.userName
    });
    

    传值路由第二种写法

    this.$router.push({
        path: "/login",
        query: {
            uname: this.userName
        }
    });
    

    接收值的路由

    console.log("接收过来的值为:" + this.$route.query.uname);
    

    因为传值的路由使用的是get方式的传值 ,这种传值方式在VueRouter叫query传值 ,所以,在下面的路由里面取值的时候,使用this.$route.query.参数名

  2. params传值 。路径变量传值 ,可以转换成post传值

    params路由传值可以把它理解成我们express路径变量传值 ,它也可以放在地址栏里面进行传递

    传值路由第一种写法

    this.$router.push({
        path: "/login/" + this.userName
    });
    

    传值路由的第二种写法

    this.$router.push({
        name: "login",
        params: {
            uname: this.userName
        }
    });
    

    接收值的路由

    console.log("接收过来的值为:" + this.$route.params.uname);
    

    注意:在使用params传递参数的时候,我们需要在router的对象里面,找到当前的这个路由,然后去更改它的path

     {
         path: "/login/:uname", //代表当前url跳转的路径
         component: login, //代表在当前这个路径下面,我们如何显示组件(显示那一个组件)
         name: "login" //给当前路由取一个别名
     }
    

    上面的path后面是/login/:uname,这一个是我们的一个路径变量,前面的login代表路由,而后面:uname代表的是变量

  3. 通过第二种方式的params传值 ,引伸出post原理传值

    params本身确实是会把参数添加到url地址栏,但是,我们可以让它不显示出来,使用下面的方法,我们就可以把它去掉,不显示,从而内容不经过浏览器地址栏处理,直接做到传值。

    它只是把路由对象里面的路径变量给去掉了,直接使用的params传值

    注意事项:因为它把path里面的路径变量去掉了,所以不能使用path去传递值了

    this.$router.push({
        path: "/login/" + this.userName
    });
    //现在上面的方法就不可用了,而必须使用下面的方法 
    
    this.$router.push({
        name: "login",
        params: {
            uname: this.userName
        }
    });
    

    下面的这种写法,变量没有显示在路径里面,只是通过params存储,params传递,不再经过url了,这个时候,我们就可以传递大家数据,同时,也可以保证数据安全

    这一个就是vue当中变相去处理post传值

路由滚动行为

::: tip
当我们切换路由的时候,想要滚动到页面的顶部或者保持原有的滚动位置,就像重新加载页面那样。Vue Router可以轻松帮我们实现这个效果。但这个功能只在支持history.pushState的浏览器中使用。
:::

滚动到页面顶部

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // 滚动到页面顶部
    return {
      x: 0,
      y: 0
    }
  }
})

滚动到前进后退页面原始的位置

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // 滚动到前进后退页面原始的位置
    if(savedPosition) {
      return savedPosition
    } else {
      return { x:0, y: 0 }
    }
  }
})

滚动到锚点位置

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // 滚动到锚点位置
    if(to.hash) {
      return {
        selector: to.hash
      }
    } 
  }
})

路由懒加载

::: tip
随着项目的体积增大,打包后的包也越来越大,我们希望只有当我们访问某一个路由时,其对应的组件才被加载,这样就更好。要实现这一想法,需要集合Vue的异步组件和webpack代码分隔的功能。
:::

var router = new VueRouter({
  routes: [
    { path: '/order', component: () => import('@/components/order.vue') },
    { path: '/address', component: () => import('@/components/address.vue') },
    { path: '/avatar', component: () => import('@/components/avatar.vue') }
  ]
})
0

评论区