Vue Router

完整的導(dǎo)航解析流程
  • 官方文檔

  • 導(dǎo)航被觸發(fā)

  • 在失活組件(from)中調(diào)用組件內(nèi)守衛(wèi)beforeRouteLeave

    • 離開守衛(wèi)通常用來禁止用戶在還未保存修改前突然離開苦蒿。本次導(dǎo)航可以通過 next(false) 來取消
  • 調(diào)用全局的beforeEach守衛(wèi)

    • 一般被用于登錄驗(yàn)證
  • 若是導(dǎo)航至重用組件佩迟,也就是相同組件,則此時(shí)調(diào)用組件內(nèi)守衛(wèi)beforeRouteUpdate(2.2+)

  • 調(diào)用路由配置中的beforeEnter

  • 開始解析異步路由組件

    • 也就是這種形式導(dǎo)入的組件component: () => import("url")
  • 在被激活的組件中調(diào)用beforeRouteEnter

    • 該守衛(wèi)中無法使用this惫撰,因?yàn)榇藭r(shí)組件實(shí)例還未被創(chuàng)建,所以為undefined

    • 但可在next函數(shù)的參數(shù)中傳入回調(diào)函數(shù)厨钻,該回調(diào)函數(shù)參數(shù)vm夯膀,即為實(shí)例,于導(dǎo)航被確認(rèn)時(shí)執(zhí)行

    • 若是重用組件蝴蜓,則只會(huì)在第一次進(jìn)入重用組件時(shí)調(diào)用該守衛(wèi)俺猿,重用組件自身切換不會(huì)再次調(diào)用

  • 調(diào)用全局的 beforeResolve 守衛(wèi) (2.5+)

    • router.beforeEach類似押袍,區(qū)別是在導(dǎo)航被確認(rèn)之前,同時(shí)在所有組件內(nèi)守衛(wèi)和異步路由組件被解析之后汽馋,該守衛(wèi)才被調(diào)用
  • 導(dǎo)航被確認(rèn)

  • 調(diào)用全局的 afterEach 守衛(wèi)

  • 觸發(fā) DOM 更新

  • 用創(chuàng)建好的實(shí)例調(diào)用 beforeRouteEnter 守衛(wèi)中傳給 next 的回調(diào)函數(shù)

原理

hash版

  • <a href="#/dasha">dasha</a>

  • 若不為a標(biāo)簽,則監(jiān)控點(diǎn)擊事件即可

    • <span onClick="routerChange('/dasha')">dasha</span>

    • 直接傳入路徑作為參數(shù)

  • function routerChange(pathName) { location.hash = pathName; } 賦值后自動(dòng)添加#

  • 監(jiān)聽hashchange事件

  • window.addEventListener("hashchange", () => {})

  • 通過location.hash可獲取頁面hash

  • 第一次進(jìn)入該頁面時(shí)悄雅,不會(huì)有hashchange煤伟,所以可以使用DOMContentLoaded事件做初始化

    • window.addEventListener("DOMContentLoaded", () => {})

history版

  • html
<span onclick="routerChange('/')">首頁</span>
<span onclick="routerChange('/chloe')">chloe</span>
  • js

    • 通過H5中的history.pushState實(shí)現(xiàn)不刷新頁面木缝,改變url中的路徑

    • 通過popstate事件監(jiān)聽瀏覽器的前進(jìn)回退事件

    • 通過location.pathname可獲取當(dāng)前頁面路徑

function routerChange(pathName) {
  history.pushState(null, null, pathName);
}

window.addEventListener("popstate", () => {})

hash與history區(qū)別

  • hash

    • 帶有#我碟,不會(huì)和服務(wù)器產(chǎn)生交流
  • history

    • 沒有#,正常的url改變吱殉,會(huì)和服務(wù)端產(chǎn)生交流

實(shí)現(xiàn)基礎(chǔ)Vue Router

  • 便于查看 所以未模塊化
當(dāng)前路由的信息
class History {
  constructor() {
    this.current = {
      path: ""
    };
  }
}

router實(shí)例構(gòu)造函數(shù)
class VueRouter {
  constructor(options) {
    this.routesMap = this.createRouteMap(options.routes || []);
    history即為$route
    this.history = new History();
    拿到模式
    this.mode = options.mode || "hash";
    初始化route信息
    this.init();
  }

  處理路由組件信息 以路徑為key component為值
  createRouteMap(routes) {
    const routesMap = {};
    for (let i = 0; i < routes.length; i++) {
      routesMap[routes[i].path] = routes[i].component;
    }
    return routesMap;
  }

  初始化route信息
  init() {
    if (this.mode === "hash") {
      location.hash || (location.hash = "/");
      document.addEventListener("DOMContentLoaded", () => {
        this.history.current.path = location.hash.slice(1);
      });
      window.addEventListener("hashchange", () => {
        this.history.current.path = location.hash.slice(1);
      });
    } else {
      document.addEventListener("DOMContentLoaded", () => {
        this.history.current.path = location.pathname;
      });
      window.addEventListener("popstate", () => {
        this.history.current.path = location.pathname;
      });
    }
  }
}

Vue.use()會(huì)默認(rèn)調(diào)用install方法
VueRouter.install = (Vue) => {
  this.$options.router即為new VueRouter創(chuàng)建的實(shí)例
  給所有組件都混入beforeCreate鉤子 該組件的$options上若有router
  則說明該組件為根實(shí)例 因?yàn)閞outer只在new Vue()上設(shè)置了
  Vue.mixin({
    給根實(shí)例添加_router和_route屬性
    beforeCreate() {
      if (this.$options.router) {
        給_router賦值為該實(shí)例
        this._router = this.$options.router;
        給_route賦值 使用Vue的響應(yīng)式方法 在_route改變時(shí) 重新渲染頁面
        Vue.util.defineReactive(this, "_route", this._router.history.current);
      }
    }
  });

  通過Object.defineProperty而不是Vue.prototype.$router給$router賦值
  可實(shí)現(xiàn)在get方法中拿到調(diào)用$router的組件實(shí)例,this.$router
  $router即為new VueRouter所創(chuàng)建的實(shí)例
  Object.defineProperty(Vue.prototype, "$router", {
    get() {
      返回根實(shí)例上的router實(shí)例
      return this.$root._router;
    }
  });

  與$router同理
  Object.defineProperty(Vue.prototype, "$route", {
    get() {
      返回根實(shí)例上的router上的history
      return this.$root._route;
    }
  });

  router-link組件
  Vue.component("router-link", {
    props: {
      to: {
        type: String,
        require: true
      },
      tag: {
        type: String,
        default: "a"
      }
    },
    methods: {
      手動(dòng)改變hash值
      handleClick() {
        const mode = this.$router.mode;
        if (mode === "hash") {
          location.hash = this.to;
        } else {
          history.pushState(null, null, this.to);
          this.$router.history.current.path = this.to;
        }
      }
    },
    render(h) {
      const mode = this.$router.mode;
      const data = {};

      if (this.tag === "a" && mode === "hash") {
        data.attrs = { href: "#" + this.to };
      } else {
        data.on = {
          若不是a標(biāo)簽 則觸發(fā)點(diǎn)擊事件
          click: this.handleClick
        };
      }

      通過h而不是JSX來創(chuàng)建 可渲染不同的tag
      return h(this.tag, data, this.$slots.default);
    }
  });

  router-view組件
  Vue.component("router-view", {
    functional: true,
    render(h, { parent }) {
      拿到routesMap
      const routesMap = parent.$router.routesMap;
      const path = parent.$route.path;
      return h(routesMap[path]);
    }
  });
};

export default VueRouter;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市包斑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌神帅,老刑警劉巖萌抵,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绍填,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡哆档,警方通過查閱死者的電腦和手機(jī)住闯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來插佛,“玉大人雇寇,你說我怎么就攤上這事∠呛睿” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)深滚。 經(jīng)常有香客問我,道長(zhǎng)血柳,這世上最難降的妖魔是什么生兆? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任皂贩,我火速辦了婚禮昆汹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘辈末。我一直安慰自己映皆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布组去。 她就那樣靜靜地躺著步淹,像睡著了一般诚撵。 火紅的嫁衣襯著肌膚如雪寿烟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音挎塌,去河邊找鬼。 笑死硕噩,一個(gè)胖子當(dāng)著我的面吹牛缭贡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谍失,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼快鱼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼纲岭!你這毒婦竟也來了止潮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎燃乍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逗旁,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡片效,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年堤舒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舌缤。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡陵吸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出壮虫,到底是詐尸還是另有隱情囚似,我是刑警寧澤线得,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站募狂,受9級(jí)特大地震影響角雷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜雷滚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一揭措、第九天 我趴在偏房一處隱蔽的房頂上張望刻蚯。 院中可真熱鬧炊汹,春花似錦逃顶、人聲如沸充甚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽殊轴。三九已至,卻和暖如春樊零,著一層夾襖步出監(jiān)牢的瞬間驻襟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工塑悼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人楷掉。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓厢蒜,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親烹植。 傳聞我的和親對(duì)象是個(gè)殘疾皇子斑鸦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 目錄 - 1.vue-router 動(dòng)態(tài)路由匹配 - 2.router-link組件及其屬性 - 3.vue-ro...
    我跟你蔣閱讀 1,118評(píng)論 0 7
  • 介紹 vue-router是一個(gè)vue插件。其實(shí)質(zhì)是在location.hash草雕、location.replace...
    AmazRan閱讀 1,543評(píng)論 0 6
  • 回憶: 我們知道巷屿,h5的history或者h(yuǎn)ash幫助我們解決了,變化url跳轉(zhuǎn)頁面不發(fā)送請(qǐng)求墩虹,并且我們能監(jiān)聽到u...
    LoveBugs_King閱讀 3,636評(píng)論 0 5
  • 前言 最近再刷Vue周邊生態(tài)的官方文檔嘱巾,因?yàn)橹暗膶W(xué)習(xí)都是看視頻配合著文檔,但主要還是通過視頻學(xué)習(xí)诫钓,所以很多知識(shí)點(diǎn)...
    聽聞北歌有初心閱讀 387評(píng)論 0 0
  • 這是一篇集合了從如何查看 vue-router源碼(v3.1.3),到 vue-router源碼解析问拘,以及擴(kuò)展了相...
    尤小小閱讀 5,510評(píng)論 2 14