美文网首页
VUE学习笔记三——vue-router

VUE学习笔记三——vue-router

作者: 青城墨阕 | 来源:发表于2019-04-16 19:10 被阅读0次

    窗外的绿色满满撞入我的眼睛,柳絮隔着纱窗热情的邀舞,可惜我不能出去。好了,这些都是题外话。

一、实现原理

vue-router 三种运行模式:

  1. hash: 使用 URL hash 值("#")来作路由。默认模式。
  2. history: 依赖 HTML5 History API 和服务器配置。
  3. abstract: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。
  • ps:在vue-router中是通过mode这一参数控制路由的实现模式的:
var router = new VueRouter({
  mode: 'history', //默认是hash
  routes: [
    ...
  ]
});
hash模式.jpg HTML5History.jpg
Hash模式
  1. hash(“#”)符号的本来作用是加在URL中指示网页中的位置;
  2. '#'符号本身以及它后面的字符称之为hash,可通过window.location.hash属性读取。它具有如下特点:
  • hash虽然出现在URL中,但不会被包括在HTTP请求中。它是用来指导浏览器动作的,对服务器端完全无用,因此,改变hash不会重新加载页面;
  • 可以为hash的改变添加监听事件:
window.addEventListener("hashchange", funcRef, false)
  • 每一次改变hash(window.location.hash),都会在浏览器的访问历史中增加一个记录。
    HashHistory.push()
push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
  this.transitionTo(location, route => {
    pushHash(route.fullPath)
    onComplete && onComplete(route)
  }, onAbort)
}

function pushHash (path) {
  window.location.hash = path
}
  • 由此可见,push()方法最主要的是对window的hash进行了直接赋值:
window.location.hash = route.fullPath 
  • hash的改变会自动添加到浏览器的访问历史记录中。


    HashHistory.push().jpg

HashHistory.replace()

  • replace()方法与push()方法不同之处在于,它并不是将新路由添加到浏览器访问历史的栈顶,而是替换掉当前的路由:
replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
  this.transitionTo(location, route => {
    replaceHash(route.fullPath)
    onComplete && onComplete(route)
  }, onAbort)
}
  
function replaceHash (path) {
  const i = window.location.href.indexOf('#')
  window.location.replace(
    window.location.href.slice(0, i >= 0 ? i : 0) + '#' + path
  )
}
  • 可以看出,它与push()的实现结构上基本相似,不同点在于它不是直接对window.location.hash进行赋值,而是调用window.location.replace方法将路由进行替换。
HTML5History模式
  1. window.history.pushState(stateObject, title, URL)
  2. window.history.replaceState(stateObject, title, URL)
  • stateObject: 当浏览器跳转到新的状态时,将触发popState事件,该事件将携带这个stateObject参数的副本。
  • title: 所添加记录的标题(暂时没有用处)。
  • URL: 所添加记录的URL。
    这两个方法有个共同的特点:当调用他们修改浏览器历史记录栈后,虽然当前URL改变了,但浏览器不会立即发送请求该URL,这就为单页应用前端路由“更新视图但不重新请求页面 ”提供了基础。
    history.pushState.jpg
    history.replaceState().jpg
两种模式比较
  1. 在一般的需求场景中,hash模式与history模式是差不多的,但几乎所有的文章都推荐使用history模式,理由是:"#" 符号太丑 ";
  2. 当然,严谨的我们肯定不应该用颜值评价技术的好坏。根据MDN的介绍,调用history.pushState()相比于直接修改hash主要有以下优势:
  • pushState设置的新URL可以是与当前URL同源的任意URL;而hash只可修改#后面的部分,故只可设置与当前同文档的URL
  • pushState设置的新URL可以与当前URL一模一样,这样也会把记录添加到栈中;而hash设置的新值必须与原来不一样才会触发记录添加到栈中
  • pushState通过stateObject可以添加任意类型的数据到记录中;而hash只可添加短字符串
  • pushState可额外设置title属性供后续使用

二、使用

1.路由文件的定义

/*
* 路由器模块
* */
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter);

import Home from '../views/home'
import Messages from '../views/messages'
import MessagesDetail from '../views/messagesDetail'


function loadView(view) {
  return () => import(`@/views/${view}.vue`)
}

var router = new VueRouter({
  mode: 'history',
  routes: [
    {
      name: 'app',
      path: '/',
      // component: App,
      redirect: '/home',
    },
    {
      name: 'about',
      path: '/about',
      component: loadView('about'),
      children: [
        {
          name: 'news',
          path: '/about/news',
          component: loadView('news')
        },
        {
          name: 'messages',
          path: '/about/messages',
          component: Messages,
          children: [
            {
              path: '/about/messages/:id',
              component: MessagesDetail,
              //主要用于写某个指定路由跳转时需要执行的逻辑
              beforeEnter: (to, from, next) => {
                console.log('beforeEnter-to: ', to)
                console.log('beforeEnter-from: ', from)
                next();
              },
              afterEnter: (to, from, next) => {
                console.log('---afterEnter-to: ', to)
                console.log('---afterEnter-from: ', from)
                next()
              }
            },
          ],
          /*
          *某个路由的路由钩子函数
          */
          //主要用于写某个指定路由跳转时需要执行的逻辑
          beforeEnter: (to, from, next) => {
            console.log('beforeEnter-to: ', to)
            console.log('beforeEnter-from: ', from)
            next();
          },
          afterEnter: (to, from, next) => {
            console.log('-----afterEnter-to: ', to)
            console.log('-----afterEnter-from: ', from)
            next()
          }
        },
      ]
    },
    {
      name: 'home',
      path: '/home',
      component: Home,
    }
  ]
});
 /*
  *全局路由钩子
  */
//这类钩子主要作用于全局,一般用来判断权限,以及以及页面丢失时候需要执行的操作
router.beforeEach((to, from, next) => {
  console.log('beforeEach-to: ', to)
  console.log('beforeEach-from: ', from)
  next();
})
router.afterEach((to, from, next) => {
  console.log('afterEach-to: ', to)
  console.log('afterEach-from: ', from)
})
export default router

vue-router的结构.jpg
  • 另:需将路由全局注入main.js
import Vue from 'vue'
import App from './App.vue'
import router from '@/router'
import less from 'less'
Vue.use(less)

require('./assets/style/iconfont.css')

Vue.config.productionTip = false; //作用是阻止 vue 在启动时生成生产提示
new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

三、有关知识点

1. router 与 route

先上一张图来:


routerPKroute.jpg
  • 由此可见,router是VueRouter的一个对象,通过Vue.use(VueRouter)和VueRouter的构造函数得到的实力对象,该对象是一个全局对象,包含了许多关键对象与属性,例如:history:
methods: {
        go(num){
          if (num === 1){
            this.$router.replace({ name: 'news' })
          }else if (num === 2){
            this.$router.push({ name: 'messages' })
          }
        }
      },
  • $route是一个当前路由的路由对象,每个路由都会有一个route对象,是一个局部对象,可获取对应的name,path,params,query等
<h3>ID:{{$route.params.id}}</h3>

2. 路由钩子(分三类)

在使用那部分已经贴出完整的代码,以及应用场景,故此处只做简单的列举:

  • 全局路由钩子
    ——这类钩子主要作用于全局,一般用来判断权限,以及以及页面丢失时候需要执行的操作
router.beforeEach((to, from, next) => {
  next();
})
router.afterEach((to, from, next) => {
})
  • 某个路由独有的路由钩子
    ——主要用于写某个指定路由跳转时需要执行的逻辑
beforeEnter: (to, from, next) => {
     next();
},
afterEnter: (to, from, next) => {
    next()
}
  • 路由组件内的路由钩子
export default {
    name: "messages",
    data() {
      return {}
    },
    beforeRouteEnter (to, from, next) {
      // 在渲染该组件的对应路由被 confirm 前调用
      // 不能获取组件实例 `this`
      // 因为当钩子执行前,组件实例还没被创建
      next();
    },
    beforeRouteUpdate (to, from, next) {
      // 在当前路由改变,但是该组件被复用时调用
      // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
      // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
      // 可以访问组件实例 `this`
      next()
    },
    beforeRouteLeave (to, from, next) {
      // 导航离开该组件的对应路由时调用
      // 可以访问组件实例 `this`
      next()
    }
  }

3. 子路由

<router-link :to="`/about/messages/${v.id}`" class="">{{v.content}}</router-link>
<keep-alive>
      <router-view></router-view>
</keep-alive>
 .router-link-active{
        color: burlywood !important;
  }

相关文章

网友评论

      本文标题:VUE学习笔记三——vue-router

      本文链接:https://www.haomeiwen.com/subject/cutiwqtx.html