【Vue2.0】黑马课程笔记(四)Vue-router

1 路由的基本概念与原理

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

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

1.1 后端路由:

  • 概念:根据不同的用户URL请求,返回不同的内容。
  • 本质:URL请求地址与服务器资源之间的对应关系。是由服务器端进行实现,并完成资源的分发
    在这里插入图片描述

1.2 SPA (Single Page Application)

  • 后端渲染(存在性能问题)
  • Ajax前端渲染(前端渲染提高性能,但是不支持浏览器的前进后退操作)
  • SPA(Single Page Application)单页面应用程序:整个网站只有一个页面,内容的变化通过Ajax局部更新实现、同时支持浏览器地址栏的前进和后退操作
  • SPA实现原理之一:基于URL地址的hash(hash的变化会导致浏览器记录访问历史的变化、但是hash的变化不会触发新的URL请求)
  • 在实现SPA过程中,最核心的技术点就是前端路由

1.3 前端路由

是依靠hash值(锚链接)的变化进行实现

  • 后端路由性能相对前端路由来说较低,所以,我们接下来主要学习的是前端路由

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

  • 本质:用户事件与事件处理函数之间的对应关系。前端路由主要做的事情就是监听事件并分发执行事件处理函数
    在这里插入图片描述

  • 简单使用:前端路由是基于hash值的变化进行实现的(比如点击页面中的菜单或者按钮改变URL的hash值,根据hash值的变化来控制组件的切换),核心实现依靠一个事件,即监听hash值变化的事件

      // 监听 window 的 onhashchange 事件,根据获取到的最新的 hash 值,切换要显示的组件的名称
      window.onhashchange = function() {
      // 通过 location.hash 获取到最新的 hash 值
     }
    

思路:
1.在页面中有一个vue实例对象,vue实例对象中有四个组件,分别是tab栏切换需要显示的组件内容,在页面中有四个超链接。
2.当我们点击这些超链接的时候,就会改变url地址中的hash值,当hash值被改变时,就会触发onhashchange事件。在触发onhashchange事件的时候,我们根据hash值来让不同的组件进行显示

    <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.slice(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>

在这里插入图片描述

2 Vue-router的基本使用

2.1 Vue-router简介

  • 它是一个Vue.js官方提供的路由管理器。( 官网链接)是一个功能更加强大的前端路由器,推荐使用。
  • Vue Router和Vue.js非常契合,可以一起方便的实现SPA(single page web application,单页应用程序)应用程序的开发。
  • Vue Router依赖于Vue,所以需要先引入Vue,再引入Vue Router
  • Vue Router的特性:
    • 支持H5历史模式或者hash模式
    • 支持嵌套路由
    • 支持路由参数
    • 支持编程式路由
    • 支持命名路由
    • 支持路由导航守卫
    • 支持路由过渡动画特效
    • 支持路由懒加载
    • 支持路由滚动行为

2.2 Vue Router的使用步骤(导入js)

1.导入js文件
2.添加路由链接
3.添加路由占位符(最后路由展示的组件就会在占位符的位置显示)
4.定义路由组件
5.配置路由规则并创建路由实例
6.将路由挂载到Vue实例中

1.导入js文件
<script src="lib/vue_2.5.22.js"></script>
<script src="lib/vue-router_3.0.2.js"></script>

2.添加路由链接:<router-link>是路由中提供的标签,默认会被渲染为a标签,to属性默认被渲染为href属性,
to属性的值会被渲染为#开头的hash地址
默认情况下,Vue 使用 a标签来渲染 router-link标签,可以通过router-link标签 tag 属性来指定用什么标签渲染
<router-link to="/user">User</router-link>
<router-link to="/login">Login</router-link>

3.添加路由填充位(路由占位符), 将来通过路由规则匹配到的组件,将会被渲染到router -view所在的位置。
<router-view></router-view>

4.定义路由组件
var User = { template:"<div>This is User</div>" }
var Login = { template:"<div>This is Login</div>" }

5.配置路由规则并创建路由实例***
var myRouter = new VueRouter({
    //routes是路由规则数组
    routes:[
        //每一个路由规则都是一个对象,对象中至少包含path和component两个属性
        //path表示  路由匹配的hash地址,component表示路由规则对应要展示的组件对象
        {path:"/user",component:User},
        {path:"/login",component:Login}
    ]
})

6.mian.js中:将路由挂载到Vue实例中
new Vue({
    el:"#app",
    //通过router属性挂载路由对象
    router:myRouter
})

在这里插入图片描述

2.3 常用:安装和使用vue-router

  • Vue路由vue-router是官方的路由插件,能够轻松的管理 SPA 项目中组件的切换。
  • Vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来
  • vue-router 目前有 3.x 的版本和 4.x 的版本,vue-router 3.x 只能结合 vue2 进行使用,vue-router 4.x 只能结合 vue3 进行使用
  • 安装:npm install vue-router@4

2.3.1 整体步骤(vue-router 3.x)

第一步:安装vue-router
npm install vue-router --save
注:有可能出错,因为会安装最新的,如果搭配vue2的话用npm install vue-router@3

第二步:在模块化工程中使用它(因为是一个插件,所以可以通过Vue.use()来安装路由功能)

  • 导入路由对象,并且调用Vue.use(VueRouter)
  • 创建路由实例,并且传入路由映射配置
  • 在Vue实例中挂载创建的路由实例

2.3.2 具体步骤:

第一步:创建路由组件
第二步:配置路由映射:组件和路径映射关系
第三步:使用路由:通过<router-link>和<router-view>

  1. 创建router实例:router/index.js中
//引入vue
import Vue from 'vue';
//引入vue-router
import VueRouter from 'vue-router';
import page1  from '../components/page1.vue'; //引用page1页面
import page2  from '../components/page2.vue'; //引用page2页面

//1.第三方库需要use一下才能用
Vue.use(VueRouter)


//2. 创建VueRouter对象,定义routes路由的集合,数组类型
const routes=[
   {//默认跳转到page1
      path: '/',
      redirect: '/page1'
    },
    //单个路由均为对象类型,path代表的是路径,component代表组件
    {path:'/page1',component:page1},
    {path:"/page2",component:page2}
]

//实例化VueRouter并将routes添加进去
//默认情况下,路径的改变使用的URL的 hash,修改的话routers后添加mode: 'history'
const router=new VueRouter({
//ES6简写,等于routes:routes
    routes
});

//3.抛出这个这个实例对象方便外部读取以及访问
export default router
  1. 挂载到Vue实例,main.js中
import Vue from 'vue'
import App from './App.vue'
//1.引用router.js
import router from './router'
Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  //2.一定要注入到vue的实例对象上
  router
}).$mount('#app')

  1. 修改App.vue,使用路由
  • router-link定义页面中点击触发部分,会被渲染成一个<a>标签。
  • router-view定义页面中显示部分,会根据当前的路径,动态渲染出不同的组件。
<template>
  <div id="app">
     <!-- 声明路由链接 -->
    <router-link to="/page1">Page1</router-link>
    <router-link to="/page2">Page2</router-link>
   <!-- 声明路由占位标签 -->
    <router-view></router-view>
  </div>
</template>

<script>

export default {
  name: 'App',
  components: {
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

router-link属性介绍:

  • to:用于指定跳转的路径
  • tag:tag可以指定<router-link>之后渲染成什么组件,比如我们下面的代码会被渲染成一个<li>元素,而不是<a> 。 如:<router-link to='/home' tag='li'>
  • replace:replace不会留下history记录,所以指定replace的情况下,后退键返回不能返回到上一个页面中
  • active-class:当<router-link>对应的路由匹配成功时,会自动给当前元素设置一个router-link-active的class,设置active-class可以修改默认的名称

2.3.3 路由重定向

  • 路由重定向指的是:用户在访问地址A的时候,强制用户跳转到地址C,从而展示特定的组件页面;
  • 可以通过路由重定向为页面设置默认展示的组件,在路由规则中添加一条路由规则即可,如下:
var myRouter = new VueRouter({
   //routes是路由规则数组
    routes: [
        //path设置为/表示页面最初始的地址 / ,redirect表示要被重定向的新地址,设置为一个路由即可
        { path:"/",redirect:"/user"},
        { path: "/user", component: User },
        { path: "/login", component: Login }
    ]
})

2.3.4 嵌套路由Children

什么是嵌套路由?
嵌套路由也称之为子路由,就是在被切换的组件中又切换其他子组件
例如:在one界面中又有两个按钮,通过这两个按钮进一步切换one中的内容
一般都是这种,子路由定义到一级路由里面
常见用处:导航栏、面包屑、侧边栏
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.3.5 路由懒加载

路由懒加载的方式

  • 方式一:结合Vue的异步组件和Webpack的代码分析
    const Home = resolve => { require. ensure(['../ components/Home.vue'], () => { resolve(require('../ components/Home.vue')) })};
  • 方式二:AMD写法
    const About = resolve => require([' ../ components/ About.vue'], resolve);
  • 方式三:在ES6中,我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割
    const Home = () => import(' . ./ components/Home.vue ' )
    在这里插入图片描述

2.4 路由跳转的两种方式

2.4.2 编程式的导航 router.push

通过调用JavaScript形式的AP|实现导航的方式,叫做编程式导航
编程式导航传递参数有两种类型:字符串、对象。

  1. 字符串
    字符串的方式是直接将路由地址以字符串的方式来跳转,这种方式很简单但是不能传递参数:this.$router.push("home");
  2. 对象
    想要传递参数主要就是以对象的方式来写,分为两种方式:命名路由、查询参数,下面分别说明两种方式的用法和注意事项。
  • 命名路由
    命名路由的前提就是在注册路由的地方需要给路由命名,命名路由传递参数需要使用params来传递,这里一定要注意使用params不是query。目标 页面接收传递参数时使用params
    特别注意:命名路由这种方式传递的参数,如果在目标页面刷新是会出错的
    使用方法如下:
this.$router.push({ name: 'news', params: { userId: 123 }})
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <button @click="routerTo">click here to news page</button>
  </div>
</template>
 
<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  methods:{
    routerTo(){
      this.$router.push({ name: 'news', params: { userId: 123 }});
      // this.$router.push('/page1');
    }
  }
}
</script>

接受传递的参数:

<template>
  <div>
    this is the news page.the transform param is {{this.$route.params.userId}}
  </div>
</template>
  • 查询参数
    查询参数其实就是在路由地址后面带上参数和传统的url参数一致的,传递参数使用query而且必须配合path来传递参数而不能用name,目标页面接收传递的参数使用query。
    注意:和name配对的是params,和path配对的是query
    使用方法如下:
this.$router.push({ path: '/news', query: { userId: 123 }});

接收参数如下:

<template>
  <div>
    this is the news page.the transform param is {{this.$route.query.userId}}
  </div>
</template>

2.4.3 声明式的导航 router-link

通过点击链接实现导航的方式,叫做声明式导航

  1. 字符串
<router-link to="news">click to news page</router-link>

(1)通过URL参数参数(?key=value&key-value),通过this.$route.query.key获取

在这里插入图片描述
在组件的生命周期中通过以下方式获取数据 this.$route.query.name this.$route.query.age

(2)通过占位符传递(路由规则中/:key/:key,路径中/value/value),通过this.$route.params.key获取

在这里插入图片描述
在这里插入图片描述
获取还是在组件的声明周期中this.$route.params.namethis.$route.params.age

2.4.4 二者比较

  • this.$router.push()
    想要导航到不同的URL,使用router.push()方法,这个方法会向history栈添加一个新纪录,所以,当用户点击浏览器后退按钮时,会回到之前的URL
  • 当点击 <router-link> 时,这个方法会在内部调用,即点击 <router-link :to="..."> 等同于调用 router.push(...)
  • a) 声明式:
     b) 编程式:router.push(…)
     c) 该方法的参数可以是一个字符串路径,或者一个描述地址的对象。
// 字符串
router.push('home')
 
// 对象
this.$router.push({path: '/login?url=' + this.$route.path});
 
// 命名的路由
router.push({ name: 'user', params: { userId: 123 }})
 
// 带查询参数,变成/backend/order?selected=2
this.$router.push({path: '/backend/order', query: {selected: "2"}});
 
// 设置查询参数
this.$http.post('v1/user/select-stage', {stage: stage})
      .then(({data: {code, content}}) => {
            if (code === 0) {
                // 对象
                this.$router.push({path: '/home'});
            }else if(code === 10){
                // 带查询参数,变成/login?stage=stage
                this.$router.push({path: '/login', query:{stage: stage}});
           }
});
 
// 设计查询参数对象
let queryData = {};
if (this.$route.query.stage) {
    queryData.stage = this.$route.query.stage;
}
if (this.$route.query.url) {
    queryData.url = this.$route.query.url;
}
this.$router.push({path: '/my/profile', query: queryData});

2.4.5 动态路由

就是占位符传递参数,应用场景:通过动态路由参数的模式进行路由匹配

//路由组件 通过$route.params.id来获取路径传参的数据
var User = { template:"<div>用户:{{$route.params.id}}</div>"}

var myRouter = new VueRouter({
    //routes是路由规则数组
    routes: [
        //通过/:参数名  的形式传递参数 ,动态路径参数以冒号开头
        { path: "/user/:id", component: User },        
    ]
})

2.5 传递参数的方式

2.5.1 命名路由name

  • 命名路由的配置规则: 为了更加方便的表示路由的路径,可以给路由规则起一个别名, 即为“命名路由’.
var myRouter = new VueRouter({
    //routes是路由规则数组
    routes: [
        //通过name属性为路由添加一个别名
        { path: "/user/:id", component: User, name:"user"},
    ]
})

添加了别名之后,可以使用别名进行跳转

<router-link to="/user">User</router-link>
<router-link :to="{ name:'user' , params: {id:123} }">User</router-link>

//还可以编程式导航
myRouter.push( { name:'user' , params: {id:123} } )

最后总结:路由传递参数和传统传递参数是一样的,命名路由类似表单提交而查询就是url传递,在vue项目中基本上掌握了这两种传递参数就能应付大部分应用了,最后总结为以下两点:
1.命名路由搭配params,刷新页面参数会丢失
2.查询参数搭配query,刷新页面数据不会丢失
3.接受参数使用this.$router后面就是搭配路由的名称就能获取到参数的值

2.5.2 获取参数的两种常用方法:params和query

  • params的类型:
    • 配置路由格式:/router/:id
    • 传递的方式:在path后面跟上对应的值
    • 传递后形成的路径:/router/123,/router/abc
  • query的类型:
    • 配置路由格式:/router,也就是普通配置
    • 传递的方式:对象中使用query的key作为传递方式
    • 传递后形成的路径:/router?id= 123,/router?id=abc

首先简单说一下$router$route的区别

//$router : 是路由操作对象,只写对象
//$route : 路由信息对象,只读对象
 
//操作 路由跳转
this.$router.push({
      name:'hello',
      params:{
          name:'word',
          age:'11'
     }
})
 
//读取 路由参数接收
this.name = this.$route.params.name;
this.age = this.$route.params.age;

2.5.3 query与path

query传递参数 query传参要用path来引入
1)由于动态路由也是传递params的,所以在 this.$router.push() 方法中path不能和params一起使用,否则params将无效。需要用name来指定页面,即通过路由配置的name属性访问

//query传参,使用path跳转
this.$router.push({
    path:'/second',
    query: {
        queryId:'20180822',
        queryName: 'query'
    }
})
 
//query传参接收
this.queryName = this.$route.query.queryName;
this.queryId = this.$route.query.queryId;

2.5.4 params与name

params传递参数(命名路由)
注:使用params传参只能使用name进行引入

 //params传参 使用name
this.$router.push({
  name:'second',
  params: {
    id:'20180822',
     name: 'query'
  }
})
 
//params接收参数
this.id = this.$route.params.id ;
this.name = this.$route.params.name ;
 
//路由
{
path: '/second/:id/:name',
name: 'second',
component: () => import('@/view/second')
}

2.5.5 总结

params是路由的一部分,必须要在路由后面添加参数名。query是拼接在url后面的参数,没有也没关系。
params一旦设置在路由,params就是路由的一部分,如果这个路由有params传参,但是在跳转的时候没有传这个参数,会导致跳转失败或者页面会没有内容。如果路由后面没有 /:id/:name,地址栏没有参数

  • 传参可以使用params和query两种方式。
  • 使用params传参只能用name来引入路由,即push里面只能是name:’xxxx’,不能是path:’/xxx’,因为params只能用name来引入路由,如果这里写成了path,接收参数页面会是undefined!!!。
  • 使用query传参使用path来引入路由。
  • params是路由的一部分,必须要在路由后面添加参数名。query是拼接在url后面的参数,没有也没关系。
  • 二者还有点区别,直白的来说query相当于get请求,页面跳转的时候,可以在地址栏看到请求参数,而params相当于post请求,参数不会再地址栏中显示。

2.6 导航守卫

vue-router提供的导航守卫主要用来拦截导航,让它完成跳转或取消。

  • to:Route:即将要进入的目标路由。
  • from:Route:当前导航正要离开的路由。
  • next:在守卫方法中如果声明了next形参,则必须调用 next() 函数,否则不允许用户访问任何一个路由
  • 直接放行:next(),强制其跳转到登录页面:next(‘/login’)

这里参考el-admin里的router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from "@/views/Login";
import User from "@/views/system/user";
import Role from "@/views/system/role";
import {getToken} from "@/utils/auth";

Vue.use(VueRouter)

const routes = [
    {
        path: '/login',
        name: 'Login',
        component: Login
    },
    {
        path: '/',
        name: 'Dashboard',
        component: () => import('@/views/Home'),
        children: [
            {
                path: 'system/user',
                name: 'User',
                component: User
            },
            {
                path: 'system/role',
                name: 'Role',
                component: Role
            }
        ]
    }
]

const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
})

//假如用户A没有登录,访问了Login页面
router.beforeEach((to, from, next) => {
    if (getToken() !== 'undefined' && getToken()) {//已登录
        if (to.name === 'Login') next('/') // 如果访问的是登陆页面,直接跳转到主页
        else next() //想去哪里就去哪里
    } else if (to.name !== 'Login')
        //没有登录
        next({name: 'Login'}) //如果不是登陆页面,重定向到登陆页面
    else next() //如果是登陆页面,就直接放行
})

export default router

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值