vue---vue-router

215 阅读6分钟

本篇是关于路由的学习。来源于王红元老师和各位大佬的文章。

1.什么是路由

通过互联的网络把信息从源地址传输到目的地址的活动。

路由器提供了两种机制: 路由和转送 路由是决定数据包从来源到目的地的路径. 转送将输入端的数据转移到合适的输出端.

路由表:本质上就是一个映射表, 决定了数据包的指向

2.后端渲染和前端渲染

后端渲染阶段(jsp):获取url地址,在服务器上直接渲染好页面 发送给前端

后端路由:后端处理url和页面之间的映射关系,当我们在页面中需要请求不同路径内容的时候,交给服务器来进行处理,服务器渲染好整个页面,并且将页面返回给客户端,这种情况下渲染好的页面,不需要单独加载任何js和css,可以直接交给浏览器展示,有利于SEO优化。

客户端 =>静态服务器资源 =>服务端

前后端分离阶段:通过ajax分离前后端,后端负责提供数据,不负责任何阶段的内容,通过ajax获取数据,并且通过Javascript将数据渲染到页面中

前端渲染(js):浏览器中显示的网页中的大部分内容,都是由前端写的js代码在浏览器中执行,最终渲染出来的网页

单页面富应用阶段(spa) 前后端分离+前端路由 前端路由:配置映射关系,一个url对应一个组件

核心:改变url,但是页面不进行整体的刷新,前端自行监听url的改变

3.url的hash和html5的history

1.hash锚点(#):通过监听浏览器的onhashchange()事件变化,查找对应的路由规则。hash模式在每次刷新页面时是直接更改#后的东西,本质上是改变window.locationhref属性。

2.history原理: 利用H5的新增的两个API pushState() replaceState() 和一个事件onpopstate监听URL变化。

history每次刷新会重新向后端重新请求服务器。history模式URL要和后端进行一致,如果后端没有及时响应,就会报错404!history的好处是可以进行修改历史记录,并且不会立刻像后端发起请求。

history.pushState():添加一个url,可以返回
history.replaceState():替代原来的url,不能返回
history.go(num):num表示前进或后退(负值)

两者区别(面试)

1.表现形式的区别
hash: 带#参数在 "" 之后通过 "&" 拼接。

例:xxx.com/#/playlist?…

history: 没有 "#" ,参数在路径中。

例:xxx.com/playlist/21…

2.原理的区别:

hash模式是基于锚点和 onhashchange事件实现的,将锚点的值作为路由地址,当地址发生变化时触发onhashchange事件,根据路径决定页面上呈现的内容。因为向服务器发送请求不会带#后面的内容,因此修改#后面的内容不会触发浏览器的刷新,不会去请求服务器。

history模式是基于Html5中的 history Api:history.pushState(IE10以上才支持)和history.replaceState方法实现的。

history.push history.pushState方法的区别是,history.pushState方法不会请求服务器,只会改变导航栏的地址并记录历史。

vue-router

1.安装

npm install vue-router --save

2.创建router/index.js文件夹

import Vue from 'vue' 
import VueRouter from 'vue-router' 

Vue.use(VueRouter)

3.创建router实例

import Vue from 'vue'
import VueRouter from 'vue-router'

// 1.安装插件
Vue.use(VueRouter)

// 2.创建router
const routes = [
]
const router = new VueRouter({
  routes,
  mode: 'history'
})


export default router

4.挂载到Vue实例中

//main.js中
import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

5.配置组件和路径的映射关系

const Home = () => import('../views/home/Home')
const routes = [
  {
    path: '',
    component: '/home'
  },
]

6.使用路由

<router-link to='/home'/>
<router-view></router-view>

<router-link to='/xxx'>: 该标签是一个vue-router中已经内置的组件, 它会被渲染成一个<a>标签
<router-link>还有一些其他属性:

tag:可以指定<router-link>之后渲染成什么组件(vue-router4.x开始,该属性被废除)

replace: 不会留下history记录, 所以指定replace的情况下, 后退键返回不能返回到上一个页面中

active-class: 处于被点击状态,当<router-link>对应的路由匹配成功时, 会自动给当前元素设置一个 router-link-activeclass名

作用:给被点击的设置样式。设置active-class可以修改默认的名称 但是通常不会修改类的属性, 会直接使用默认的router-link-active即可. 

<router-view>:(占位符)(组件渲染的位置) 该标签会根据当前的路径, 动态渲染出不同的组件,网页的其他内容, 比如顶部的标题/导航, 或者底部的一些版权信息等会和<router-view处于同一个等级。 在路由切换时, 切换的是<router-view>挂载的组件, 其他内容不会发生改变.

7.redirect是重定向:一开始跳转到默认的地址上

path配置的是根路径: / 也就是我们将根路径重定向到/home的路径下

{
    path: '/',
    redirect: '/home'
  },

8.默认情况下改变的hash的地址,想要更换模式

const router = new VueRouter({
  routes,
  mode: 'history'
})

动态路由

路径不确定,在path里定义参数项:id在路径中使用一个动态字段来实现,我们称之为 路径参数 : this.$route.params.id:可以拿到后续的路由参数信息 谁处于被选中状态,$route就为该状态的组件

//router/index.js
const routes = [
  {
    path: '/home/:id',
    component: '/home'
  },
]
//动态路由配置 App.vue
<router-link :to="'/user'+Id"/>
//拿到动态路由参数
<p>{{$route.params.id}}</p>
  data(){
    return{
        Id:'11111'
    }
 }

路由懒加载(用的时候再加载)

作用:将路由对应的组件打包成一个个的js代码块.只有在这个路由被访问到的时候, 才加载对应的组件

方式一: 结合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')

嵌套路由

{
    path: '/home',
    component: UserHome,
    meta: {
      activeNum: 0
    },
    children: [
      {
        path: '/home/searchPopup',
        name: 'SearchPopup',
        // 路由懒加载
        component: () => import(/* webpackChunkName: "SearchPopup" */ '../views/SearchPopup.vue')

      }
    ]
  },
<router-link to='/home/searchPopup'></router-link>
<router-view></router-view>

编程式导航

调用API的方法实现导航的方式

(1)this.$router.push('/xxx'):跳转到指定hash地址,并增加一条历史记录,可以进行后退或前进

(2)this.$router.replace('/xxx):跳转到指定的hash地址,并替换掉当前的hash地址,页面不可后退或前进,只存在一条历史记录

(3)this.$router.go(n):n表示数值,前进or后退 this.$router.back() 后退 this.$router.forward前进

传递参数的的方式

1.query(大量传递参数)

配置路由格式: /router, 也就是普通配置

传递的方式: 对象中使用query的key作为传递方式

传递后形成的路径: /router?id=123, /router?id=abc

获取参数:$route.query.xxx

2.params

配置路由格式:/router/:id

传递方式:在path后面跟上对应的值/router/123

3.两种方式

第一种:在跳转时就设置参数

<router-link to="{
                path:'/user/'+123,
                query:{name:'why':age:18 
                }"
  ></router-link>

第二种:通过this.$router.push()

methods: {
    // 跳转至详情页
    toPruductDetail(id) {
      // query传递参数
      this.$router.push('/pruductDetail?id=' + id)
      //完整版
      this.$router.push({
          path:'/user/'+123,
          query:{name:'why',age:18}
      })
    }
  }

4.获取参数 {{$route.query/params.id}}

router 和route 的由来

$routerVueRouter实例,想要导航到不同URL,则使用$router.push方法

$route为当前router跳转对象里面可以获取name、path、query、params等

导航守卫

vue-router提供的导航守卫主要用来监听路由的进入和离开的.beforeEachafterEach的钩子函数, 它们会在路由即将改变前和改变后触发.

导航钩子的三个参数解析:

to: 即将要进入的目标的路由对象.

from: 当前导航即将要离开的路由对象.

next: 调用该方法后, 才能进入下一个钩子.

//前置路由守卫(全局守卫) 配置在router/index.js中
router.beforeEach((to, from, next) => {
//判断用户有无登录
 const token = localStorage.getItem('token')
  if (to.path === '/cart') {
    if (token) {
      next()
    } 
//必须有next()
  next()
})

路由元信息

有时,你可能希望将任意信息附加到路由上,如过渡名称、谁可以访问路由等。这些事情可以通过接收属性对象的meta属性来实现,并且它可以在路由地址和导航守卫上都被访问到。定义路由的时候你可以这样配置 meta 字段:

const routes = [
  {
    path: '/posts',
    component: PostsLayout,
    children: [
      {
        path: 'new',
        component: PostsNew,
        // 只有经过身份验证的用户才能创建帖子
        meta: { requiresAuth: true }
      },
      {
        path: ':id',
        component: PostsDetail
        // 任何人都可以阅读文章
        meta: { requiresAuth: false }
      }
    ]
  }
]

keep-alive

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。(组件缓存) 它们有两个非常重要的属性:

include - 字符串或正则表达,只有匹配的组件会被缓存

exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存

router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存

只有该组件使用了keep-alive时才有以下两个生命周期函数

当组件被缓存时,自动触发 deactivated

当组件被激活时,自动触发 activated