日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

如何手寫簡易的 Vue Router

瀏覽:151日期:2022-11-16 15:05:40

前言

還是那樣,懂得如何使用一個常用庫,還得了解其原理或者怎么模擬實現,今天實現一下 vue-router 。

有一些知識我這篇文章提到了,這里就不詳細一步步寫,請看我 手寫一個簡易的 Vuex

基本骨架

Vue 里面使用插件的方式是 Vue.use(plugin) ,這里貼出它的用法:

安裝 Vue.js 插件。如果插件是一個對象,必須提供 install 方法。如果插件是一個函數,它會被作為 install 方法。install 方法調用時,會將 Vue 作為參數傳入。這個方法的第一個參數是 Vue 構造器,第二個參數是一個可選的選項對象。

全局混入

使用 Vue.mixin(mixin)

全局注冊一個混入,影響注冊之后所有創建的每個 Vue 實例。可以使用混入向組件注入自定義的行為,它將影響每一個之后創建的 Vue 實例。

路由用法

比如簡單的:

// 路由數組const routes = [ { path: ’/’, name: ’Page1’, component: Page1, }, { path: ’/page2’, name: ’Page2’, component: Page2, },]const router = new VueRouter({ mode: ’history’, // 模式 routes,})

它是傳入了mode和routes,我們實現的時候需要在VueRouter構造函數中接收。

在使用路由標題的時候是這樣:

<p> <!-- 使用 router-link 組件來導航. --> <!-- 通過傳入 `to` 屬性指定鏈接. --> <!-- <router-link> 默認會被渲染成一個 `<a>` 標簽 --> <router-link to='/page1'>Go to Foo</router-link> <router-link to='/page2'>Go to Bar</router-link></p><!-- 路由出口 --><!-- 路由匹配到的組件將渲染在這里 --><router-view></router-view>

故我們需要使用Vue.component( id, [definition] )注冊一個全局組件。

了解了大概,我們就可以寫出一個基本骨架

let Vue = nullclass VueRouter { constructor(options) { this.mode = options.mode || ’hash’ this.routes = options.routes || [] }}VueRouter.install = function (_Vue) { Vue = _Vue Vue.mixin({ beforeCreate() { // 根組件 if (this.$options && this.$options.router) { this._root = this // 把當前vue實例保存到_root上 this._router = this.$options.router // 把router的實例掛載在_router上 } else if (this.$parent && this.$parent._root) { // 子組件的話就去繼承父組件的實例,讓所有組件共享一個router實例 this._root = this.$parent && this.$parent._root } }, }) Vue.component(’router-link’, { props: { to: { type: [String, Object], required: true, }, tag: { type: String, default: ’a’, // router-link 默認渲染成 a 標簽 }, }, render(h) { let tag = this.tag || ’a’ return <tag href={this.to}>{this.$slots.default}</tag> }, }) Vue.component(’router-view’, { render(h) { return h(’h1’, {}, ’視圖顯示的地方’) // 暫時置為h1標簽,下面會改 }, })}export default VueRouter

mode

vue-router有兩種模式,默認為 hash 模式。

history 模式

通過window.history.pushStateAPI 來添加瀏覽器歷史記錄,然后通過監聽popState事件,也就是監聽歷史記錄的改變,來加載相應的內容。

popstate 事件

當活動歷史記錄條目更改時,將觸發 popstate 事件。如果被激活的歷史記錄條目是通過對 history.pushState()的調用創建的,或者受到對 history.replaceState()的調用的影響,popstate 事件的 state 屬性包含歷史條目的狀態對象的副本。

History.pushState()方法

window.history.pushState(state, title, url)

該方法用于在歷史中添加一條記錄,接收三個參數,依次為:

state:一個與添加的記錄相關聯的狀態對象,主要用于popstate事件。該事件觸發時,該對象會傳入回調函數。也就是說,瀏覽器會將這個對象序列化以后保留在本地,重新載入這個頁面的時候,可以拿到這個對象。如果不需要這個對象,此處可以填null。 title:新頁面的標題。但是,現在所有瀏覽器都忽視這個參數,所以這里可以填空字符串。 url:新的網址,必須與當前頁面處在同一個域。瀏覽器的地址欄將顯示這個網址。

hash 模式

使用 URL 的 hash 來模擬一個完整的 URL。,通過監聽hashchange事件,然后根據hash值(可通過 window.location.hash 屬性讀取)去加載對應的內容的。

繼續增加代碼,

let Vue = nullclass HistoryRoute { constructor() { this.current = null // 當前路徑 }}class VueRouter { constructor(options) { this.mode = options.mode || ’hash’ this.routes = options.routes || [] this.routesMap = this.createMap(this.routes) this.history = new HistoryRoute() // 當前路由 this.initRoute() // 初始化路由函數 } createMap(routes) { return routes.reduce((pre, current) => { pre[current.path] = current.component return pre }, {}) } initRoute() { if (this.mode === ’hash’) { // 先判斷用戶打開時有沒有hash值,沒有的話跳轉到 #/ location.hash ? ’’ : (location.hash = ’/’) window.addEventListener(’load’, () => { this.history.current = location.hash.slice(1) }) window.addEventListener(’hashchange’, () => { this.history.current = location.hash.slice(1) }) } else { // history模式 location.pathname ? ’’ : (location.pathname = ’/’) window.addEventListener(’load’, () => { this.history.current = location.pathname }) window.addEventListener(’popstate’, () => { this.history.current = location.pathname }) } }}VueRouter.install = function (_Vue) { Vue = _Vue Vue.mixin({ beforeCreate() { if (this.$options && this.$options.router) { this._root = this this._router = this.$options.router Vue.util.defineReactive(this, ’_route’, this._router.history) // 監聽history路徑變化 } else if (this.$parent && this.$parent._root) { this._root = this.$parent && this.$parent._root } // 當訪問this.$router時即返回router實例 Object.defineProperty(this, ’$router’, { get() { return this._root._router }, }) // 當訪問this.$route時即返回當前頁面路由信息 Object.defineProperty(this, ’$route’, { get() { return this._root._router.history.current }, }) }, })}export default VueRouter

router-link 和 router-view 組件

VueRouter.install = function (_Vue) { Vue = _Vue Vue.component(’router-link’, { props: { to: { type: [String, Object], required: true, }, tag: { type: String, default: ’a’, }, }, methods: { handleClick(event) { // 阻止a標簽默認跳轉 event && event.preventDefault && event.preventDefault() let mode = this._self._root._router.mode let path = this.to this._self._root._router.history.current = path if (mode === ’hash’) { window.history.pushState(null, ’’, ’#/’ + path.slice(1)) } else { window.history.pushState(null, ’’, path.slice(1)) } }, }, render(h) { let mode = this._self._root._router.mode let tag = this.tag || ’a’ let to = mode === ’hash’ ? ’#’ + this.to : this.to console.log(’render’, this.to) return ( <tag on-click={this.handleClick} href={to}> {this.$slots.default} </tag> ) // return h(tag, { attrs: { href: to }, on: { click: this.handleClick } }, this.$slots.default) }, }) Vue.component(’router-view’, { render(h) { let current = this._self._root._router.history.current // current已經是動態響應 let routesMap = this._self._root._router.routesMap return h(routesMap[current]) // 動態渲染對應組件 }, })}

至此,一個簡易的vue-router就實現完了,案例完整代碼附上:

let Vue = nullclass HistoryRoute { constructor() { this.current = null }}class VueRouter { constructor(options) { this.mode = options.mode || ’hash’ this.routes = options.routes || [] this.routesMap = this.createMap(this.routes) this.history = new HistoryRoute() // 當前路由 // 初始化路由函數 this.initRoute() } createMap(routes) { return routes.reduce((pre, current) => { pre[current.path] = current.component return pre }, {}) } initRoute() { if (this.mode === ’hash’) { // 先判斷用戶打開時有沒有hash值,沒有的話跳轉到 #/ location.hash ? ’’ : (location.hash = ’/’) window.addEventListener(’load’, () => { this.history.current = location.hash.slice(1) }) window.addEventListener(’hashchange’, () => { this.history.current = location.hash.slice(1) }) } else { // history模式 location.pathname ? ’’ : (location.pathname = ’/’) window.addEventListener(’load’, () => { this.history.current = location.pathname }) window.addEventListener(’popstate’, () => { this.history.current = location.pathname }) } }}VueRouter.install = function(_Vue) { Vue = _Vue Vue.mixin({ beforeCreate() { // 根組件 if (this.$options && this.$options.router) { this._root = this // 把當前vue實例保存到_root上 this._router = this.$options.router // 把router的實例掛載在_router上 Vue.util.defineReactive(this, ’_route’, this._router.history) // 監聽history路徑變化 } else if (this.$parent && this.$parent._root) { // 子組件的話就去繼承父組件的實例,讓所有組件共享一個router實例 this._root = this.$parent && this.$parent._root } // 當訪問this.$router時即返回router實例 Object.defineProperty(this, ’$router’, { get() { return this._root._router }, }) // 當訪問this.$route時即返回當前頁面路由信息 Object.defineProperty(this, ’$route’, { get() { return this._root._router.history.current }, }) }, }) Vue.component(’router-link’, { props: { to: { type: [String, Object], required: true, }, tag: { type: String, default: ’a’, }, }, methods: { handleClick(event) { // 阻止a標簽默認跳轉 event && event.preventDefault && event.preventDefault() // 阻止a標簽默認跳轉 let mode = this._self._root._router.mode let path = this.to this._self._root._router.history.current = path if (mode === ’hash’) { window.history.pushState(null, ’’, ’#/’ + path.slice(1)) } else { window.history.pushState(null, ’’, path.slice(0)) } }, }, render(h) { let mode = this._self._root._router.mode let tag = this.tag || ’a’ let to = mode === ’hash’ ? ’#’ + this.to : this.to return ( <tag on-click={this.handleClick} href={to}> {this.$slots.default} </tag> ) // return h(tag, { attrs: { href: to }, on: { click: this.handleClick } }, this.$slots.default) }, }) Vue.component(’router-view’, { render(h) { let current = this._self._root._router.history.current // current已經是動態 let routesMap = this._self._root._router.routesMap return h(routesMap[current]) // 動態渲染對應組件 }, })}export default VueRouter

ps: 個人技術博文 Github 倉庫,覺得不錯的話歡迎 star,給我一點鼓勵繼續寫作吧~

以上就是如何手寫簡易的 Vue Router的詳細內容,更多關于手寫簡易的 Vue Router的資料請關注好吧啦網其它相關文章!

標簽: Vue
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲午夜免费| 四虎4545www国产精品| 色综合视频一区二区三区日韩 | 欧美aa在线视频| 国产精品二区不卡| 美日韩精品视频| 国产日产精品_国产精品毛片| 国产一区二区三区四区大秀| 国产精品日本| 国产精品久av福利在线观看| 999久久久精品国产| 亚洲三级av| 国产伦久视频在线观看| 亚洲一区二区三区免费在线观看| 国产人成精品一区二区三| 亚洲午夜视频| 国产精品一区免费在线| 久久精品国产68国产精品亚洲| 日韩精品乱码av一区二区| 日韩电影免费网址| 青草国产精品| 亚洲成人精选| 国产精品久久久久蜜臀| 日本午夜精品一区二区三区电影 | 精品三级在线观看视频| 亚洲一区国产| 久久91视频| 亚洲午夜精品久久久久久app| 欧美精选一区二区三区| 91福利精品在线观看| 激情不卡一区二区三区视频在线| 精品一区在线| 五月激激激综合网色播| 国内在线观看一区二区三区| 免播放器亚洲一区| 国产高潮在线| 亚洲精品系列| 久久九九电影| 欧美极品中文字幕| 蜜臀久久99精品久久久久宅男| 欧美精品福利| 亚洲天堂黄色| 97久久亚洲| 91精品99| 丝袜诱惑一区二区| 亚洲精品少妇| 久久婷婷久久| 风间由美中文字幕在线看视频国产欧美| 热久久国产精品| 成人午夜国产| 色婷婷综合网| 欧美aa在线视频| 日av在线不卡| re久久精品视频| 精品一区二区三区免费看| 无码日韩精品一区二区免费| 久久伦理在线| 久久精品亚洲一区二区| 日本午夜免费一区二区| 久久国产精品99国产| 99久久亚洲精品| 日韩成人综合| 久久影院午夜精品| 日本激情一区| 精品国产成人| 精品国产中文字幕第一页| 国产伦精品一区二区三区视频| 日韩一区二区免费看| 欧美日韩尤物久久| 日本国产欧美| 日韩欧美中文字幕电影| 亚洲免费黄色| 国产尤物精品| 99精品国产一区二区三区| аⅴ资源天堂资源库在线| 麻豆一区二区三| 精品国产精品久久一区免费式| 国产亚洲久久| 国产欧美日韩视频在线| 亚洲欧美日韩综合国产aⅴ| 日本少妇一区| 国产福利91精品一区二区| 97久久中文字幕| 亚洲三级av| 国产免费av国片精品草莓男男| 免费看的黄色欧美网站| 九九久久电影| 好吊视频一区二区三区四区| 精品欧美久久| 天堂资源在线亚洲| 亚洲二区精品| 激情综合亚洲| 夜夜嗨一区二区| 视频一区在线播放| 丝袜亚洲精品中文字幕一区| 日韩伦理在线一区| 日韩精品免费视频人成| 日本成人在线不卡视频| 日韩精品亚洲专区| 青青伊人久久| 国产精品tv| 国际精品欧美精品| 久久久久.com| 亚洲在线久久| 国产高清亚洲| 久久影院一区| 中文视频一区| 久久91视频| 激情欧美一区二区三区| 亚洲精品黄色| 精品视频网站| 亚洲激情国产| 欧美日韩中出| 亚洲午夜视频| 日韩精品免费视频人成| 里番精品3d一二三区| 亚洲午夜91| 日本一区二区三区中文字幕| 日韩欧美午夜| 一区二区三区四区精品视频| 美日韩一区二区三区| 亚洲高清av| 91精品一区| 欧美日韩一区二区三区视频播放| 日韩视频1区| 92国产精品| 亚洲+小说+欧美+激情+另类| 精品国产麻豆| 中文字幕一区二区三区日韩精品| 国产精品主播在线观看| 99久久婷婷这里只有精品| 日韩精品乱码av一区二区| 青青青免费在线视频| 日韩精品免费观看视频| 人人精品亚洲| 国产精品777777在线播放| 在线视频免费在线观看一区二区| 老色鬼精品视频在线观看播放| 精品在线播放| 精品国产aⅴ| 亚洲精品日韩久久| 激情久久婷婷| 欧美成人一二区| 首页亚洲欧美制服丝腿| 在线精品亚洲欧美日韩国产| 日韩av中文字幕一区| 久久香蕉国产| 美女久久99| 亚洲精品大全| 婷婷精品进入| 日韩不卡一区| 日韩不卡一区二区| 五月天综合网站| 国产成人调教视频在线观看| 日韩精品一区二区三区中文| 欧美日韩国产在线观看网站| 精品亚洲a∨| 欧美亚洲专区| 美女网站一区| 欧洲一区二区三区精品| 欧美a级一区二区| 亚洲97av| 国产精品美女久久久| 亚洲精品永久免费视频| 国产精品亚洲片在线播放| 蜜臀av一区二区在线免费观看| 欧美性感美女一区二区| 精品国产三区在线| 国产精品久久| 欧美精品福利| 日韩一区二区三免费高清在线观看| 女人av一区| 亚洲网站视频| 韩国精品主播一区二区在线观看| 国产精品**亚洲精品| 91精品国产自产观看在线 | 中文字幕日韩高清在线| 亚洲免费播放| 欧美亚洲国产激情| 不卡福利视频| 久久电影tv| 最新中文字幕在线播放 | 你懂的国产精品| 911亚洲精品| 久久免费大视频| 久久久久国产精品一区二区| 日韩av二区| 国产一区二区三区不卡视频网站 | 国产精品腿扒开做爽爽爽挤奶网站| 成人日韩在线| 亚洲涩涩在线| 久久久久91| 欧美不卡高清| 午夜日韩av| 久久都是精品| 亚洲资源在线| 日本va欧美va精品发布| 国产日韩欧美一区二区三区 | 黄色网一区二区| 美女av在线免费看|