[TOC]

认识路由

  • 说起路由想到了什么?
    • 路由是一个网络工程里面的术语
    • 路由(routing)就是通过互联的网络把信息从源地址传输到目的地址的活动
  • 简单理解

    • 在生活中,我们听说过的就是路由器
    • 路由器是做什么的呢?
    • 它内部提供了两种机制:路由和转发
      • 路由决定数据包从来源到目的地的路径
      • 转发则有路由器根据其内部的映射表,将信息转发给正确的终端设备

        什么是前端渲染?什么是后端渲染?

  • 网页开发历史之阶段一:

    • 这一阶段主要是后端渲染,使用的是jsp/php/c#等语言开发,html+css+jsp(java server page),此时输入url,服务器端就直接将页面生成好了,其中的java代码就是将数据库中的数据显示在页面上,然后直接将生成好的网页发送给浏览器,这时发送的代码只有html+css,这就叫做后端渲染
    • 如果此时页面发生了点击,进行了页面跳转,就会将新的url发送到服务器,服务器进行解析后,和上面的流程一样,在服务端渲染好页面,再发送给浏览器,如果有更多的点击,都是同样的流程
    • 后端渲染定义:后端处理URL和页面之间的映射关系,但是一个网站有很多页面,服务器该如何处理呢?就是通过正则对发送过来的URL进行匹配,并交给一个Controller进行处理,处理完成后生成页面发送给前端,这就完成了一个IO操作,且有利于SEO的优化。缺点:前端后端混合在一起,非常不利于维护
  • 网页开发历史之阶段二:
    • 前后端分离阶段:随着ajax的出现而出现的,此时,后端只负责提供服务器+数据库,
    • 服务器是分为两种的:一种是提供静态资源的服务器,另一种是提供API借口的服务器,前者用来存放一些html,图片等资源,用于让url来加载页面的,后者是用来放一些数据的,用于让ajax来请求一些数据并返回
    • 浏览器输入URL后,回去静态资源服务器拿到对应的html+css+js,而html+css浏览器可以直接渲染显示,而js代码则需要浏览器来执行,比如$.ajax(url:…;srccess:….;…),这时浏览器就会再向API接口服务器发送请求来请求一些资源,这时浏览器拿到了「大量数据」,再通过其他js代码将这些大量数据插入到标签中,这时浏览器再渲染到整个页面中
    • 这就叫前端渲染,这时最大的优点就是前后端责任的清晰,后端专注于数据上,前端专注于交互和可视化上,并且当移动端(iOS/Android)出现后,后端不需要进行任何处理,依然使用之前的一套API即可,目前很多网页还是使用这种方式来开发。
  • 网页开发历史之阶段三:

    • 单页面富应用阶段:主要特点就是在前后端分离的基础上加了一层前端路由,这时,整个网页只有一个html页面就是index.html,甚至可能只有一个css文件,这时如果输入一个URL,就会去静态资源服务器请求这个网页的html+css+js(全部资源),目前可以理解为开发的网站只有一个html,一个css,一个js。
    • 这时,如果想要实现点击页面显示不同内容的话,就需要一个技术作为支撑:前端路由,它的内部会配置一些映射关系,比如当我们点击首页按钮时,URL就会发生改变 xxxx.com/home类似于这种,不过不同于之前的URL,之前的URL发生了改变,就会重新去静态资源服务器请求新的页面,而现在的点击首页按钮,生成的新URL是不会重新去服务器请求资源的,它之后通过js代码的判断,去抽取出来用于显示我们首页的那一部分代码来放在对应位置进行显示
    • 总结就是:前端路由的核心就是改变URL,但是页面不进行整体的刷新,如何实现呢?有如下两种方案

      URL的hash和H5的history模式

  • URL的hash也就是锚点(#),本质上是改变window.location的href属性

    • 我们可以通过直接赋值location.hash来改变href,但是页面不会发生刷新,我们只需要配置一下路由即可实现网页不刷新跳转。
    • location.hash = '/home'
  • H5中提供了一种新的方法就是History
    • history.pushState({}, '', '/home')压入一个新的地址,会保留历史记录,使用history.back()方法会返回上一次输入的地址
    • history.replaceState({}, '', '/home')替换掉原来的地址,不会保留历史记录
    • history.go(-1)就相当于history.back(),就是找之前的历史记录
    • history.forward()则等价于history.go(1),就是前进一个地址
    • 这些接口就构成了浏览器中的前进后退等功能

vue-router的基本使用

  • 首先安装vue-router:npm install vue-router --save
  • 在模块化工程中进行使用
    • 第一步:导入路由对象,并且调用Vue.use(VueRouter)
    • 第二步:创建路由实例,并且传入路由映射配置
    • 第三步:在Vue实例中挂载创建的路由实例
  • 具体项目中
    • 首先安装好vue-router
    • 在src目录下创建一个router文件夹,并创建一个index.js文件,如下 ```javascript // 配置路由相关的信息 import VueRouter from ‘vue-router’ import Vue from ‘vue’

// 1. 通过Vue.use(插件),来安装这个插件 Vue.use(VueRouter)

// 2. 创建VueRouter对象 const routes = [

] const router = new VueRouter({ // 配置路由和组件之间的映射关系 routes })

// 3. 将router对象传入到vue实例中 export default router


   - 然后在main.js文件中导入这个文件并在vue实例上进行挂载 
- 接下来看一些配置路由的映射关系操作步骤
   - 第一步:创建路由组件
   - 第二步:配置路由映射:组件和路径的映射关系
```javascript
 {
    path: '/home',
    component: Home
  },
  {
    path: '/about',
    component: About
  }
  • 现在我们不想使用URL的hash了,因为它总有一个#,http://localhost:8080/#/home ,我们想使用H5的history来实现同样的功能

    • 很简单,直接在index.js中配置一个mode即可
      const router = new VueRouter({
      // 配置路由和组件之间的映射关系
      routes,
      mode: 'history'
      })
      
  • router-link的一些其他属性

    
    <a name="Rr9t2"></a>
    #### vue-router动态路由的使用
    
    - 在某些情况下,一个页面的path路径可能是不确定的,比如我们进入用户界面时,希望是如下的路径:
       - /user/idaaaa 或者 user/idbbb
       - 除了有前面的user固定以外,后面还跟上了不同的用户ID
       - 这种path和component的匹配关系,我们称之为动态路由(也是路由传递数据的一种方式)
    - 首先按照常规路由的配置在index.js中来配置一个'/user'路径,以及对应的User组件,然后按照如下方式进行id的添加
    ```javascript
    {
      path: '/user/:userid',
      component: User
    }
    
    • 这时在中使用时要按照如下方式使用
    • <router-link :to="'/user/'+userId">用户</router-link>将我们要拼接的userId用v-bind的方式拼接到to属性上就可以了
    • 之后如果点击某个商品,就可以动态的决定路由显示什么样的信息
      • 新增一个需求,就是把拼接上去的不同的userID在对应的User组件中进行展示
    • 在User组件中使用计算属性来获取路由中的信息,然后通过{{userId}}在User组件中进行展示

      computed: {
      userId () {
       return this.$route.params.userId
      }
      }
      
    • 这里的$route指的是活跃状态的路由,我们这里就是/user/userId,使用params.userId就可以拿到我们拼接上去的内容

    • 注意区分$router和$route,前者是我们创建的最大的路由对象,后者是处于活跃状态的路由

      路由的懒加载

    • 官方解释:当打包构建应用时,JS包会变得非常大,影响页面加载,如果我们可以把不同路由的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效了
    • 打包我们的项目时,js文件会被分为三个部分,一个是名为app的js文件,用来放我们开发时写的代码,另一个为vendor的js文件,用来放第三方的代码,最后一个为manifest的js文件,用于我们项目的一些底层支撑
    • 随着我们项目的越来越大,app文件就会越来越大,用户打开项目时就会出现短暂的延迟,用户体验很不友好,为了解决这个问题,我们的处理办法是,一个路由打包一个js文件,当我们点击某个按钮,再去服务器加载对应的组件,而不是一次性全部加载到本地
    • 懒加载:用到时再加载。主要作用就是将路由对应的组件打包成一个个的js代码块,只有当这个路由被访问到的时候,才加载对应的组件,使用方法如下 ```javascript // 之前的使用方式 import Home from ‘../component/Home’ import About from ‘../component/About’

    Vue.use(VueRouter) const routes = [ { path: ‘/home’, component: Home }, { path: ‘/about’, component: About } ]

    // 使用懒加载之后的方式 const routes = [ { path: ‘/home’, component: () => import(‘../component/Home’) }, { path: ‘/about’, component: () => import(‘../component/About’) } ]

    
    <a name="sH0hT"></a>
    ## vue-router嵌套使用
    
    - 嵌套路由是一个很常见的功能,比如home页面中,我们希望通过/home/news和/home/message访问一些内容
    - 一个路径映射一个组件,访问这两个路径
    - 实现路由嵌套有两个步骤:
       - 创建对应的子组件,并且在路由映射中配置对应的子路由
       - 在组件内部使用<router-view>标签
    - 具体使用步骤如下:
    ```javascript
    const routes = [
      {
          path: '/home',
        component: () => import('../components/Home'),
        children: [
            {
                  path: 'news',
                component: () => import('../component/HomeNews')
              },
          {
              path: 'message',
            component: () => import('../component/HomeMessage')
          }
        ]
      }
    ]
    
    • 首先配置好路由映射关系
    • 接下来让其显示在哪个位置:在Home组件内部用来让HomeNews和HomeMessage组件显示即可

    vue-router参数传递

    • 如果在路由跳转时,我们希望将一些参数随着路由跳转去特定的页面,主要有两个方式:params 和 query
    • params方式:
      • 配置路由映射关系时:/router/:id
      • 传递的方式:在父组件中使用<router-link :to="'/user/"+userId></router-link>
      • 在子组件中使用:$route.params.id来获取传递过来的值
    • query方式:
      • 配置路由映射关系时:/router,也就是普通配置
      • 传递的方式:在父组件中使用<router-link :to="{path:'/profile',query:{name:'ryan',age:23}}"></router-link>
      • 在子组件中使用:$route.query就可以获取到这个query对象
      • 如果使用query方式传递参数时,使用的不是router-link,而是使用的button按钮,要如何传递呢?
        profileClick () {
        this.$router.push({
         path: '/profile',
        query: {
           name: 'ryan',
         age: 23
        }
        })
        }
        

    vue-router导航守卫

    • 导航守卫的目的就是:监听路由的跳转,并设置一些监听函数,用来对某些跳转做一些处理
    • 考虑一些需求:在一个SPA应用中,如何改变网页的标题呢?
      • 网页标题是通过来显示的,但是SPA只有一个固定的HTML,切换不同的页面时,标题并不会改变</li><li>但是我们可以通过js来修改title中的内容:window.document.title = ‘新的标题’</li><li>那么在Vue项目中,在哪里修改,如何修改呢?</li></ul> </li><li>如果想要监听全局的路由跳转,在router下的index.js文件中,对我们创建的router对象进行如下处理: ```javascript const router = new VueRouter({~~~})</li></ul> <p>router.beforeEach(function (to, from, next) { // 从from跳转到to document.title = to.matched[0].meta.title next() })</p> <pre><code> - 在配置路由对象时,可以添加一个meta属性,表示元数据(描述数据的数据),可以添加title属性等 ```javascript const routes = [ { path: '/home', component: () => import('../components/Home'), meta: { title: '首页' } } ] </code></pre><ul> <li>上面的beforeEach我们也叫做前置守卫,在跳转前进行回调,还有一个叫afterEach,叫做后置守卫,跳转后进行回调,使用后置守卫的话,不用调用next()方法</li><li>除了上述的全局守卫之外,还有两种守卫:组件内守卫,路由独享守卫(只有我进入某个路由里面才会调用)</li></ul> <p><a name="nb2CZ"></a></p> <h2 id="23pp0d"><a name="23pp0d" class="reference-link"></a><span class="header-link octicon octicon-link"></span>keep-alive</h2><ul> <li><router-view>也是一个组件,如果直接被包在keep-alive里面,所有路径匹配到的视图组件都会被缓存</li><li>keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染</li><li>我们每次点击去一个新的组件的话,原来在的组件就会被销毁,当点回去的话,又会重新创建该组件,如果使用了keep-alive就可以避免频繁的创建销毁等情况</li><li>使用方法:<code><keep-alive><router-view /></keep-alive></code></li><li>注意:使用了keep-alive后,被包含的组件就会有了两个生命周期函数activeted(激活)和deactiveted(未激活),这两个生命周期函数用于判断当前组件是不是被点击状态,如果被点击且处于当前这个组件,就回调activeted()方法,否则回调deactiveted()方法</li><li>keep-alive中的一些属性:<ul> <li>include属性:字符串或正则表达式,只有匹配的组件才会被缓存</li><li>exclude属性:字符串或正则表达式,任何匹配的组件都不会被缓存</li><li>字符串中填入对应组件的name即可,注意这里不要加空格<pre><code class="lang-html"><keep-alive exclude="Profile,User"> <router-view /> </keep-alive> </code></pre> </li></ul> </li></ul>