Vue路由

1. 路由的基本概念

1.1. 什么是路由?

  • 路由的概念

  • 路由的本质就是一种对应关系,比如说我们在url地址中输入我们要访问的url地址之后,浏览器要去请求这个url地址对应的资源。

  • 那么url地址和真实的资源之间就有一种对应的关系,就是路由,路由是根据不同的 url 地址展示不同的内容或页面;

1.2. 路由分为哪两种?

  • 路由分为前端路由和后端路由

  • 后端路由

浏览器在地址栏中切换不同的url时,每次都向后台服务器发出请求,服务器响应请求,在后台拼接html文件传给前端显示, 返回不同的页面, 意味着浏览器会刷新页面,网速慢的话说不定屏幕全白再有新内容。后端路由的另外一个极大的问题就是 前后端不分离。早期绝大多数网站都采用后端路由的方式。

  • 优点:分担了前端的压力,html和数据的拼接都是由服务器完成。

  • 缺点:当项目十分庞大时,加大了服务器端的压力,同时在浏览器端不能输入指定的url路径进行指定模块 的访问。另外一个就是如果当前网速过慢,那将会延迟页面的加载,对用户体验不是很友好。

  • 前端路由

    • 概念:根据不同的用户事件,显示不同的页面内容

    • 本质:用户事件与事件处理函数之间的对应关系

    • 前端路由是依靠hash值(锚链接)的变化进行实现

很重要的一点是页面不刷新,前端路由就是把不同路由对应不同的内容或页面的任务交给前端来做,每跳转到不同的URL都是使用前端的锚点路由. 随着(SPA)单页应用的不断普及,前后端开发分离,目前项目基本都使用前端路由,在项目使用期间页面不会重新加载。后端路由性能相对前端路由来说较低,所以,我们接下来主要学习的是前端路由。

  • 前端路由的基本概念:根据不同的事件来显示不同的页面内容,即事件与事件处理函数之间的对应关系,

  • 前端路由主要做的事情就是监听事件并分发执行事件处理函数

  • SPA(Single Page Application)

  • SPA(Single Page Application)单页面应用程序:整个网站只有一个页面,内容的变化通过Ajax局部更新实现、同时支持浏览器地址栏的前进和后退操作

  • SPA实现原理之一:基于URL地址的hash(hash的变化会导致浏览器记录访问历史的变化、但是hash的变化不会触发新的URL请求

  • 在实现SPA过程中,最核心的技术点就是前端路由

优点:

1.用户体验好,和后台网速没有关系,不需要每次都从服务器全部获取,快速展现给用户

2.可以在览器中输入指定想要访问的url路径地址。

3.实现了前后端的分离,方便开发。有很多框架都带有路由功能模块。

缺点:

1.使用浏览器的前进,后退键的时候会重新发送请求,没有合理地利用缓存

2.单页面无法记住之前滚动的位置,无法在前进,后退的时候记住滚动的位置

1.3.前端路由的初体验

2. Vue Router简介

2.1 Vue Router的特性:

2.2 Vue Router的使用步骤(★★★)

  • 前端路由是基于hash值的变化进行实现的(比如点击页面中的菜单或者按钮改变URL的hash值,根据hash值的变化来控制组件的切换)

  • 核心实现依靠一个事件,即监听hash值变化的事件

  • window.onhashchange = function(){
        //location.hash可以获取到最新的hash值
        location.hash
    }
    <!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>Document</title>
            <!-- 导入 vue 文件 -->
            <script src="./lib/vue_2.5.22.js"></script>
        </head>
        <body>
            <!-- 被 vue 实例控制的 div 区域 -->
            <div id="app">
            <!-- 切换组件的超链接 -->
            <a href="#/zhuye">主页</a> 
            <a href="#/keji">科技</a> 
            <a href="#/caijing">财经</a>
            <a href="#/yule">娱乐</a>
    
            <!-- 根据 :is 属性指定的组件名称,把对应的组件渲染到 component 标签所在的位置 -->
            <!-- 可以把 component 标签当做是【组件的占位符】 -->
            <component :is="comName"></component>
            </div>
    
            <script>
            // #region 定义需要被切换的 4 个组件
            // 主页组件
            const zhuye = {
                template: '<h1>主页信息</h1>'
            }
    
            // 科技组件
            const keji = {
                template: '<h1>科技信息</h1>'
            }
    
            // 财经组件
            const caijing = {
                template: '<h1>财经信息</h1>'
            }
    
            // 娱乐组件
            const yule = {
                template: '<h1>娱乐信息</h1>'
            }
            // #endregion
    
            // #region vue 实例对象
            const vm = new Vue({
                el: '#app',
                data: {
                comName: 'zhuye'
                },
                // 注册私有组件
                components: {
                zhuye,
                keji,
                caijing,
                yule
                }
            })
            // #endregion
    
            // 监听 window 的 onhashchange 事件,根据获取到的最新的 hash 值,切换要显示的组件的名称
            window.onhashchange = function() {
                // 通过 location.hash 获取到最新的 hash 值
                console.log(location.hash);
                switch(location.hash.substr(1)){
                case '/zhuye':
                    vm.comName = 'zhuye'
                break
                case '/keji':
                    vm.comName = 'keji'
                break
                case '/caijing':
                    vm.comName = 'caijing'
                break
                case '/yule':
                    vm.comName = 'yule'
                break
                }
            }
            </script>
        </body>
        </html>

    核心思路: 在页面中有一个vue实例对象,vue实例对象中有四个组件,分别是tab栏切换需要显示的组件内容 在页面中有四个超链接,如下:

  • <a href="#/zhuye">主页</a> 
    <a href="#/keji">科技</a> 
    <a href="#/caijing">财经</a>
    <a href="#/yule">娱乐</a>

    1.4. 理解前端路由的核心思路

  • 通过a标签的点击改变锚点hash值

  • 使用window.onhashchange监听hash值的改变

  • 通过location.hash获取到当前的hash值并进行判断,展示hash值对应的组件

  • 它是一个Vue.js官方提供的路由管理器。是一个功能更加强大的前端路由器,推荐使用。

  • Vue Router和Vue.js非常契合,可以一起方便的实现SPA(single page web application,单页应用程序)应用程序的开发。

  • 支持H5历史模式或者hash模式

  • 支持嵌套路由

  • 支持路由参数

  • 支持编程式路由

  • 支持命名路由

  • 支持路由过渡动画特效

  • 支持路由懒加载

  • 支持路由滚动行为

  • Vue Router依赖于Vue,所以需要先引入Vue,再引入Vue Router

  • 官方参考地址:安装 | Vue Router

A.导入js文件

​    B.定义路由组件

​    C.配置路由规则并创建路由实例

​    D.将路由挂载到Vue实例中

​    E.添加路由占位符(最后路由展示的组件就会在占位符的位置显示)

​    F.添加路由链接    

A.导入js文件
<script src="lib/vue_2.5.22.js"></script>
<script src="lib/vue-router_3.0.2.js"></script>
 B.定义路由组件
var User = { template:"<div>This is User</div>" }
var Login = { template:"<div>This is Login</div>" }
C.配置路由规则并创建路由实例
var myRouter = new VueRouter({
    //routes是路由规则数组
​    routes:[
​        //每一个路由规则都是一个对象,对象中至少包含path和component两个属性
​        //path表示  路由匹配的hash地址,component表示路由规则对应要展示的组件对象
​        {path:"/user",component:User},
​        {path:"/login",component:Login}
​    ]
})
D.将路由挂载到Vue实例中
new Vue({
    el:"#app",
    //通过router属性挂载路由对象
    router:myRouter
})
E.添加路由填充位(路由占位符)
<router-view></router-view>
F.添加路由链接:

<router-link>是路由中提供的标签,默认会被渲染为a标签,to属性默认被渲染为href属性, ​ to属性的值会被渲染为#开头的hash地址

<router-link to="/user">User</router-link>
<router-link to="/login">Login</router-link>
<!DOCTYPE html>
<html lang='zh-CN'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>Document</title>
<style>
</style>
<!-- 1.导包 -->
<script src='./js/vue.js'></script>
<script src="./js/vue-router_3.0.2.js"></script>
</head>
<body>
<div id='app'>
    <!--  6.路由跳转导航 -->
     <router-link to="/login">登录</router-link>
     <router-link to="/register">注册</router-link>
     <!-- 5.路由占位符 -->
     <router-view ></router-view>
</div>
<script>
// 2.创建路由组件
const login = {
  template:"<h1>登录组件</h1>"
}
const register = {
  template:"<h1>注册组件</h1>"
}
// 3.创建路由对象,并进行路由配置
const router = new VueRouter({
  routes : [
    {path : "/login", component:login},
    {path : "/register", component:register}
  ]
})
 const vm = new Vue({
  el:'#app',
   data:{
    
 },
   methods:{
    
   },
  //  4. 路由对象挂载
   router
   })
</script>
</body>
</html>
  • 小结:

Vue Router的使用步骤还是比较清晰的,按照步骤一步一步就能完成路由操作

2.3 路由重定向:

  • 可以通过路由重定向为页面设置默认展示的组件,在路由规则中添加一条路由规则即可,如下:

  • const router = new VueRouter({
      routes : [
        // 路由重定向
        {path : "/", redirect: "/login"},
        {path : "/login", component:login},
        {path : "/register", component:register}
      ]
    })

2.4 路由切换添加动画 

.router-link-active {
      padding: 10px;
      background-color: #ccc;
      border-radius: 5px;
      color: white;
      text-decoration: none;
    }
		  linkActiveClass: 'myactive' // 手动更改类名称,改行代码与routes属性平级

2.5 路由传参的第一种方式query

使用?形式传参<router-link to="/login?id=1&&name='zs'">登录</router-link>
接收参数使用 $route.query.id
 var login = {
            template: '<h1>登录组件-------{
  {$route.query.id}}----{
  {$route.query.name}}</h1>',
        }

2.6 路由传参的第二种方式params

使用/形式传参  <router-link to="/login/12/张三">登录</router-link>
接收参数使用  $route.params.id
路由配置修改成:{ path: '/login/:id/:name', component: login },
 var login = {
        template:'<h1>登录组件-------{
  {$route.params.id}}----{
  {$route.params.name}}</h1>'
      };

2.7使用watch监听路由地址的改变

watch: {
          '$route.path': function (newval, oldval) {
            console.log(newval + '----' + oldval);
            if (newval == '/login') {
              console.log('欢迎进入登录界面');
            } else if (newval == '/register') {
              console.log('欢迎进入注册界面');
            }
          }
        }

3. 嵌套路由,动态路由的实现方式

3.1.嵌套路由的概念

  • 当我们进行路由切换的时候显示的组件中还有新的子级路由链接以及内容。

  • 嵌套路由最关键的代码在于理解子级路由的概念:

  • 比如我们有一个/login的路由

  • 那么/login下面还可以添加子级路由,如:

  • /login/account
    /login/phone

  • 参考代码如下:

  • 1.创建子路由组件.

  • const account = {
      template:"<h3>账号登录</h3>"
    }
    const phone = {
      template:"<h3>手机登录</h3>"
    }
  • 增加children嵌套属性

  • {path : "/login", component:login,children:[
        {path : "/login/account", component :account },
        {path : "/login/phone", component :phone },
    ]},

    在login组件模板内添加路由占位符与路由跳转链接

  • const login = {
      template:`<div>
        <h1>登录组件</h1>
         <router-link to="/login/account">账号登录</router-link>
         <router-link to="/login/phone">手机登录</router-link>
         <router-view ></router-view>
        </div>`
    }

    3.2.动态路由匹配

    3.2.1、什么是动态路由?

    动态路由就是可以接收参数数据的路由形式,路由地址的一部分是完全一样的,另一部分是会发生变化的,我们可以将一些动态变化的部分形成路由参数,这些路由参数就叫做动态路由匹配

    3.2.2、如何接收动态路由传递的参数?

  • $route.params

  • var myRouter = new VueRouter({
        //routes是路由规则数组
        routes: [
            //通过/:参数名  的形式传递参数 
            { path: "/user/:id", component: User },
            ]
        var User = { template:"<div>用户:{
        {$route.params.id}}</div>"}
        })

    3.3.3、通过props属性获取与传递参数

  • 如果使用$route.params.id来获取路径传参的数据不够灵活,我们可以通过props属性获取与传递参数数据的方式

  • 我们可以将props属性设置为true,route.params将会被设置为组件属性,那么组件可以通过props接收route.params,我们可以通过props来接收参数

  • var myRouter = new VueRouter({
    ​    //routes是路由规则数组
    ​    routes: [
    ​    //通过/:参数名  的形式传递参数 
    ​    //如果props设置为true,route.params将会被设置为组件属性
    ​       { path: "/user/:id", component: User,props:true },
    ​        		]
    
    })
    
    ​		var User = { 
    ​	    props:["id"],
    ​	    template:"<div>用户:{
        {id}}</div>"
    ​	    }

    还有一种情况,我们可以将props设置为对象,那么就直接将对象的数据传递给组件进行使用,但是此时,我们无法获取传递的参数值

  • var myRouter = new VueRouter({
    ​    //routes是路由规则数组
    ​    routes: [
    ​        //通过/:参数名  的形式传递参数 
    ​        //如果props设置为对象,则传递的是对象中的数据给组件
    ​        { path: "/user/:id", component: User,props:{username:"jack",age:18} },
    ​      ]  
    
    })
    
    var User = { 
        props:["username","age"],
        template: '<h1>User 组件 -- 用户id为: {
        {id}} -- 姓名为:{
        {uname}} -- 年龄为:{
        {age}}</h1>'
        }

    如果想要获取传递的参数值还想要获取传递的对象数据,那么props应该设置为函数形式。

  • var myRouter = new VueRouter({
           //routes是路由规则数组
       	    routes: [
               //通过/:参数名的形式传递参数 
               //如果props设置为函数,则通过函数的第一个参数获取路由对象
               //并可以通过路由对象的params属性获取传递的参数
               //这里的参数route,就是路由动态参数对象,path有几个参数项,route中就有几个值
            	   { path: "/user/:id", component: User,props:(route)=>{
                		   return {username:"jack",pwd:123,id:route.params.id}
                   } 
               },
               ]
       	})
    
       var User = { 
       	    props:["username","pwd","id"],
       		    template:"<div>用户:{
        {id}} -> {
        {username}}---{
        {pwd}}</div>"
       	    }

    4. 命名路由

  • 什么是命名路由?:给路由取别名

  • 案例:

  • 1 .var myRouter = new VueRouter({
        //routes是路由规则数组
    
    ​     routes: [
    ​        //通过name属性为路由添加一个别名
    ​        { path: "/user/:id", component: User, name:"user", props: true},
    ​        ]
    
    })
     2.Props:['id']

    3 . 添加了别名之后,可以使用别名进行跳转,同时可以通过params传递参数

  • <router-link to="/user">User</router-link> //传统方式
    <router-link :to="{ name:'user' , params: {id:123} }">User</router-link>
  • 这里要给to加属性绑定,以及传递对应的参数

  • 还可以编程式导航

  • myRouter.push( { name:'user' , params: {id:123} } )

    5. 编程式导航

  • 页面导航的两种方式:

    • A.声明式导航:通过点击链接的方式实现的导航,比如:<a></a><router-link></router-link>

    • B.编程式导航:调用js的api方法实现导航比如location.href

    • C.在Vue中,实现编程示导航基本语法是:this.$router.push("hash地址")和;this.$router.go( n );

  • Vue-Router中常见的导航方式:

    • this.$router.push("hash地址");

    • this.$router.push("/login");

    • this.$router.push({ name:'user' , params: {id:123} });

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

    • this.$router.push({ path:"/login",query:{username:"jack"} });

    • his.$router.go( n );//n为数字

    • this.$router.go( -1 );

    • <!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>Document</title>
          <!-- 导入 vue 文件 -->
          <script src="./lib/vue_2.5.22.js"></script>
          <script src="./lib/vue-router_3.0.2.js"></script>
        </head>
        <body>
          <!-- 被 vm 实例所控制的区域 -->
          <div id="app">
            <router-link to="/user/1">User1</router-link>
            <router-link to="/user/2">User2</router-link>
            <router-link to="/user/3">User3</router-link>
            <router-link :to="{name :'user',params:{id :123} }">User4</router-link>
            <!-- <router-link to="/register/5">Register</router-link> -->
            <router-link :to="{name :'register',params:{id :123}}">Register</router-link>
      
            <!-- 路由占位符 -->
            <router-view></router-view>
          </div>
      
          <script>
            const User = {
              props: ['id', 'uname', 'age'],
              template:`<div>
                <h1>User 组件 -- 用户id为: {
            {id}} -- 姓名为:{
            {uname}} -- 年龄为:{
            {age}}</h1>
                <button @click="goRegister">去注册</button>
                </div>`,
                methods: {
                     goRegister () {
                        //  this.$router.push("/register/456")
                         this.$router.push({name :'register',params:{id :789}})
                     }
            }
            }
      
            const Register = {
              template: `<div>
                <h1>Register 组件 -----{
            {this.$route.params.id}}</h1>
                <button @click="goBack">返回</button>
                </div>`,
                methods : {
                  goBack () {
                    this.$router.go(-1)
                  }
                }
            }
      
            // 创建路由实例对象
            const router = new VueRouter({
              // 所有的路由规则
              routes: [
                { path: '/', redirect: '/user' },
                {
                  path: '/user/:id',
                  component: User,
                  name : "user",
                  props: route => {return { uname: 'zs', age: 20, id: route.params.id }}
                },
                { path: '/register/:id',
                  component: Register,
                  name:"register"
                }
              ]
            })
      
            // 创建 vm 实例对象
            const vm = new Vue({
              // 指定控制的区域
              el: '#app',
              data: {},
              // 挂载路由实例对象
              // router: router
              router
            })
          </script>
        </body>
      </html>

6.实现后台管理案例

点击左侧的"用户管理","权限管理","商品管理","订单管理","系统设置"都会出现对应的组件并展示内容

其中"用户管理"组件展示的效果如上图所示,在用户管理区域中的详情链接也是可以点击的,点击之后将会显示用户详情信息。

案例思路: 1).先将素材文件夹中的基于vue-router的案例.html复制到我们自己的文件夹中。

看一下这个文件中的代码编写了一些什么内容,这个页面已经把后台管理页面的基本布局实现了

2).在页面中引入vue,vue-router

3).创建Vue实例对象,准备开始编写代码实现功能

4).希望是通过组件的形式展示页面的主体内容,而不是写死页面结构,所以我们可以定义一个根组件:

//只需要把原本页面中的html代码设置为组件中的模板内容即可
1.  <div id="app">
        <App></App>
    </div>
2.    const App = {
        template:`
        <div>
        <!-- 头部区域 -->
      <header class="header">管理系统</header>
      <!-- 中间主体区域 -->
      <div class="main">
        <!-- 左侧菜单栏 -->
        <div class="content left">
          <ul>
            <li>用户管理</li>
            <li>权限管理</li>
            <li>商品管理</li>
            <li>订单管理</li>
            <li>系统设置</li>
          </ul>
        </div>
        <!-- 右侧内容区域 -->
        <div class="content right"><div class="main-content">添加用户表单</div></div>
      </div>
      <!-- 尾部区域 -->
      <footer class="footer">版权信息</footer>
      </div>
        `
      }    
3.  components: {
            App
          }

5).当我们访问页面的时候,默认需要展示刚刚创建的app根组件,我们可以创建一个路由对象来完成这个事情,然后将路由挂

载到Vue实例对象中即可

const router = new  VueRouter({
        routes:[
          {path:"/",component:App}
        ]
      })

  const vm = new Vue({
          el:"#app",
          data:{},
          methods: {
            
          },
          router
      })

补充:到此为止,基本的js代码都处理完毕了,我们还需要设置一个路由占位符

<body>
  <div id="app">
        <router-view ></router-view>
    </div>
</body>

6).此时我们打开页面应该就可以得到一个VueRouter路由出来的根组件了

我们需要在这个根组件中继续路由实现其他的功能子组件

先让我们更改根组件中的模板:更改左侧li为子级路由链接,并在右侧内容区域添加子级组件占位符

const App = {
    template:`<div>
        ........
        <div class="main">
          <!-- 左侧菜单栏 -->
          <div class="content left">
            <ul>
              <!-- 注意:我们把所有li都修改为了路由链接 -->
              <li><router-link to="/users">用户管理</router-link></li>
              <li><router-link to="/access">权限管理</router-link></li>
              <li><router-link to="/goods">商品管理</router-link></li>
              <li><router-link to="/orders">订单管理</router-link></li>
              <li><router-link to="/systems">系统设置</router-link></li>
            </ul>
          </div>
          <!-- 右侧内容区域 -->
          <div class="content right">
            <div class="main-content">
                <!-- 在 -->
                <router-view></router-view> 
            </div>
          </div>
        </div>
        .......
      </div>`
  }

然后,我们要为子级路由创建并设置需要显示的子级组件,并通过路由重定向将app根组件默认导航到users

//建议创建的组件首字母大写,和其他内容区分
const Users = {template:`<div>
    <h3>用户管理</h3>
</div>`}
const Access = {template:`<div>
    <h3>权限管理</h3>
</div>`}
const Goods = {template:`<div>
    <h3>商品管理</h3>
</div>`}
const Orders = {template:`<div>
    <h3>订单管理</h3>
</div>`}
const Systems = {template:`<div>
    <h3>系统管理</h3>
</div>`}

//添加子组件的路由规则
 const router = new  VueRouter({
        routes:[
          {path:"/",component:App,
          redirect: "/users",
          children:[
                  {path:"/users",component:Users},
                  {path:"/access",component:Access},
                  {path:"/goods",component:Goods},
                  {path:"/orders",component:Orders},
                  {path:"/systems",component:Systems},
          ]},
          
        
        ]
      })

 const vm = new Vue({
          el:"#app",
          data:{},
          methods: {
            
          },
          router
      })
      
   //子组件内部  

7). 展示用户信息列表: A.为Users组件添加私有数据,并在模板中循环展示私有数据

const Users = {
      template: `<div>
        <h3>用户管理</h3>
    </div>`,
      data() {
        return {
          userList: [
            { id: 1, name: 'zs', age: 18 },
            { id: 2, name: 'ls', age: 19 },
            { id: 3, name: 'wang', age: 20 },
            { id: 4, name: 'jack', age: 21 }
          ]
        };
      }
    };
 template:`<div>
<h3>用户管理</h3>
        <table>
            <thead>
                <tr>
                    <th>编号</th>
                    <th>姓名</th>
                    <th>年龄</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <tr :key="item.id" v-for="item in userList">
                    <td>{
  {item.id}}</td>
                    <td>{
  {item.name}}</td>
                    <td>{
  {item.age}}</td>
                    <td><a href="javascript:;">详情</a></td>
                </tr>
            </tbody>
        </table>
  </div>`}

8). 当用户列表展示完毕之后,我们可以点击列表中的详情来显示用户详情信息,首先我们需要创建一个组件,用来展示详情信息,

这里需要注意的是当我们点击详情的时候,users组件消失了,对应显示的应该是详情页的组件,所以,我们的详情页应该是和之前创建的用户管理等5个子组件是平级关系,接下来创建UserInfo子组件,并匹配路由规则

//定义组件
const UserInfo ={template:`<div>
  <h3>用户详情</h3>
  </div>`
}

//定义路由规则
									{path:"/users",component:Users},
                  {path:"/userinfo",component:UserInfo},
                  {path:"/access",component:Access},
                  {path:"/goods",component:Goods},
                  {path:"/orders",component:Orders},
                  {path:"/systems",component:Systems},

9). 此时点击用户管理组件中的a标签,我们希望可以跳转到对应的详情页,并拿到点击的信息的编号

<tbody>
                <tr :key="item.id" v-for="item in userList">
                    <td>{
  {item.id}}</td>
                    <td>{
  {item.name}}</td>
                    <td>{
  {item.age}}</td>
                    <td><a href="javascript:;" @click="goDetail(item.id)">详情</a></td>
                </tr>
            </tbody>
            
      	//Users    组件中的data和method   
           data(){
        return {
            userList:[
                {id:1,name:"zs",age:18},
                {id:2,name:"ls",age:19},
                {id:3,name:"wang",age:20},
                {id:4,name:"jack",age:21},
            ]
        }
         },
         methods: {
  			  goDetail(id) {
   			   console.log(id);
  		  }
  }    

10). 通过编程式导航实现路由的跳转,传入id的同时,在路由规则中把id的位置标记为动态参数

//编程式导航实现路由的跳转并传入id
  goDetail(id) {
      console.log(id);
      this.$router.push("/userinfo/"+id)
    }
   	//在路由规则中将id标记为动态参数 
  children:[
                  {path:"/users",component:Users},
                  {path:"/userinfo/:id",component:UserInfo},
                  {path:"/access",component:Access},
                  {path:"/goods",component:Goods},
                  {path:"/orders",component:Orders},
                  {path:"/systems",component:Systems},
          ]},   

11). 在用户详情页中获取传递过来的编号,推荐使用props:true

//.1.路由规则使用props
  {path:"/userinfo/:id",component:UserInfo,props: true},
  // 2.在userinfo组件中定义id,并且引用到页面上
  const UserInfo ={template:`<div>
  <h3>用户详情-----用户id为{
  {id}}</h3>
  </div>`,
  props: ['id']

}

12). 在详情页中提供一个后退按钮,实现后退功能

const UserInfo ={template:`<div>
  <h3>用户详情-----用户id为{
  {id}}</h3>
  <button @click="goback">后退</button>
  </div>`,
  props: ['id'],
  methods: {
    goback () {
    //实现后退功能
      this.$router.go(-1)
    }
  }

}

7、路由守卫

  • Vue-router中的路由守卫,主要是对其内容进行保护,如果没有对应的权限,则不允许访问。

我们首先来看一下全局守卫,也就是所有的路由都会经过全局守卫来进行检测。

//实现全局守卫
      router.beforeEach((to, from, next) => {
        //to:去哪个页面,from来自哪个页面,next继续执行.
        //判断哪个路由需要进行守卫,这里可以通过元数据方式
        if (to.meta.auth) {
          if (window.isLogin) {
            next();
          } else {
            next("/login?redirect=" + to.fullPath);
          }
        } else {
          next();
        }
      });

在上面的代码中,创建了路由守卫,但是需要判断的是需要对哪个路由进行守卫,这里就是通过元数据来进行判断的。如果所跳转到的路由有元数据,并且对应的auth属性为true表明是需要进行守卫的,那么下面就需要校验用户是否登录,这里是通过判断否window.isLogin的值是否为true来进行判断的(这里简化了操作,实际应用中应该存储到sessionStorage),如果条件成立则表明用户登录,就继续访问用户希望访问到的页面,否则跳转到登录页面,而且将用户希望访问的页面地址也传递到了登录页面,这样用户登录成功后,可以直接跳转到要访问的页面。

如果没有元数据,则继续访问用户要访问的页面。演示如下:

首先创建login组件,代码如下:

const Login = {
        data() {
          return {
            isLogin: window.isLogin,
          };
        },

        template: `<div>
          <button @click="login" v-if="!isLogin">登录</button>
          <button @click="logout" v-else>注销</button>
          </div>`,
        methods: {
          login() {
            window.isLogin = true;
            this.$router.push(this.$route.query.redirect);
          },
          logout() {
            this.isLogin = window.isLogin = false;
          },
        },
      };

在上面的代码中创建了login组件,下方代码给users,access,systems,userinfo都添加了元数据,并配置了login路由规则

const router = new VueRouter({
      routes: [
        {
          path: '/login',
          component: Login
        },
        {
          path: '/',
          component: App,
          redirect: '/users',
          children: [
            {
              path: '/users',
              component: Users,
              meta: {
                auth: true
              }
            },
            {
              path: '/access',
              component: Access,
              meta: {
                auth: true
              }
            },
            {
              path: '/goods',
              component: Goods
            },
            {
              path: '/orders',
              component: Orders
            },
            {
              path: '/systems',
              component: Systems,
              meta: {
                auth: true
              }
            },
            {
              path: '/userinfo/:id',
              component: UserInfo,
              props: true,
              meta: {
                auth: true
              }
            }
          ]
        }
      ]
    });  

配置全局路由守卫:

//实现全局守卫
    router.beforeEach((to, from, next) => {
        //to:去哪个页面,from来自哪个页面,next继续执行.
        //判断哪个路由需要进行守卫,这里可以通过元数据方式
        if (to.meta.auth) {
          if (window.isLogin) {
            next();
          } else {
          // console.log(to.fullPath);
            next("/login?redirect=" + to.fullPath);
          }
        } else {
          next();
        }
      });

打开浏览器发现,我们的重定向被修改至登录页

当单击登录按钮后,进行将window.isLogin设置为true, 并且进行跳转至原页面。

8、addRoutes动态路由添加

在前面的案例中,我们都是将路由定义好,然后通过路由守卫来判断,某个用户是否登录,从而决定能否访问某个路由规则对应的组件内容。

但是,如果某些路由规则只能用户登录以后才能够访问,那么我们也可以不用提前定义好,而是在登录后,通过addRoutes方法为其动态的添加。

首先这里还需要全局的路由守卫来进行校验判断,只不过这里全局路由守卫的逻辑发生了变化。

9、Hash模式与History模式

Hash模式与History模式区别

  • 前端路由中,不管是什么实现模式,都是客户端的一种实现方式,也就是当路径发生变化的时候,是不会向服务器发送请求的。

  • 如果需要向服务器发送请求,需要用到ajax方式。

  • 两种模式的区别

  • 首先是表现形式的区别

hash模式中路径带有#, #后面的内容作为路由地址。可以通过问号携带参数。

当然这种模式相对来说比较丑,路径中带有与数据无关的符号,例如#?

  • History模式

  • https://www.baidu.com/showlist/22256

  • History模式是一个正常的路径的模式,如果要想实现这种模式,还需要服务端的相应支持。

  • 下面再来看一下两者原理上的区别。

  • Hash模式是基于锚点,以及onhashchange`事件。

  • 通过锚点的值作为路由地址,当地址发生变化后触发onhashchange事件。

  • History模式是基于HTML5中的History API`

  • 也就是如下两个方法

  • history.pushState( ) IE10以后才支持

  • history.replaceState( )`

  • 更改方式:添加下方属性即可:

  • // mode: "history", 需要运行在服务器端

相关推荐

  1. vue3

    2024-01-29 08:46:02       46 阅读
  2. Vue

    2024-01-29 08:46:02       39 阅读
  3. Vue

    2024-01-29 08:46:02       34 阅读
  4. <span style='color:red;'>Vue</span><span style='color:red;'>路</span><span style='color:red;'>由</span>

    Vue

    2024-01-29 08:46:02      28 阅读
  5. [Vue]

    2024-01-29 08:46:02       19 阅读
  6. vue-详解

    2024-01-29 08:46:02       17 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-29 08:46:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-29 08:46:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-29 08:46:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-29 08:46:02       20 阅读

热门阅读

  1. 【洛谷题解】P1706 全排列问题

    2024-01-29 08:46:02       38 阅读
  2. Redis 事务

    2024-01-29 08:46:02       34 阅读
  3. MyBatis框架-XML映射器

    2024-01-29 08:46:02       24 阅读
  4. 关键点标注工具

    2024-01-29 08:46:02       28 阅读
  5. VUE computed和watch例子

    2024-01-29 08:46:02       31 阅读
  6. [EFI]戴尔T5810电脑 Hackintosh 黑苹果efi引导文件

    2024-01-29 08:46:02       36 阅读
  7. 非root运行docker容器

    2024-01-29 08:46:02       41 阅读