自定義插件vue-router簡單實現hashRouter設計思路

步驟

1.掛載 vue.prototype.$router

2.聲明兩個組件

router-view this.$router.current=>component => h(component)

router-link h('a',{attrs:{href:'#'+this.to}},this.$slots.default)

3.url的監聽:window hashchange的改變

4.定義響應式current,defineReactive()

實現VueRouter類

let Vue
// vueRouter是一個類,一個插件
class VueRouter {constructor(options) {this.$options = options}
}VueRouter.install = function (_Vue) {//保存引用Vue = _Vue//掛在一下vueRouter到vue原型//利用全局混入,全局執行代碼,在vue實例beforeCreate時獲取到router,因為在main.js中生成vue實例在VueRouter掛載到Vue之后,所以常規無法獲取到router,Vue.mixin({beforeCreate() {if (this.$options.router) { //避免每次實例創建都觸發,只有根實例上存在的才觸發。Vue.prototype.$router = this.$options.router}}})//聲明兩個全局組件,router-viewport,router-linkVue.component('router-link', {props: {to: {type: String,required: true}},//預編譯情況下,template是不能使用的,這里要使用render// template:'<a>123</a>'render(h) {// return <a href={'#'+this.to}>{this.$slots.default}</a> jsx語法也可以使用return h('a', {attrs: { href: "#" + this.to }}, this.$slots.default) //this.$slots.default 獲取內容}})Vue.component('router-view', {render(h) {return h('div', 'router-view')}})
}export default VueRouter

這里有個難點,就是如何將router掛載到vue原型上,我們采用了mixin的用法,在vue實例beforeCreate時獲取到router,并掛在到實例上。

怎么理解呢?在router.js中,Vue.use(VueRouter)觸發install方法,但是在此時,并沒有生成router,是在new VueRouter之后生成的router,并且掛載到了Vue,此時才有VueRouter,利用全局混入,延遲執行掛載到Vue原型上,這樣就可以獲取到router實例了。

import Vue from 'vue'
// import VueRouter from 'vue-router'
import VueRouter from '@/krouter/kvue-router'
Vue.use(VueRouter)//執行install方法,router還未被創建
const routes = [{path: '/home',name: 'home',component: () => import('@/components/Home.vue')},{path: '/about',name: 'about',component: () => import('@/components/About.vue')},
]const router = new VueRouter({routes
})
export default router
import Vue from 'vue'
import App from './App.vue'
import router from './router/router'Vue.config.productionTip = falsenew Vue({router,render: h => h(App),
}).$mount('#app')

監聽url變化,渲染組件

class VueRouter {constructor(options) {this.$options = options//聲明一個響應式current//渲染函數如果壓重復執行,必須依賴響應式數據Vue.util.defineReactive(this,'current',window.location.hash.slice(1) || '/') //需要#后面的部分//監聽url變化window.addEventListener('hashchange', () => {this.current = window.location.hash.slice(1)})}
}

這里使用Vue工具類定義響應式current,必須是響應式current,否則不生效,在router-view處讀取并渲染對應組件,在這里Vue的原型對象已經掛載了this.$router,this.$router又是VueRouter的實例,所以在這上面能夠找到對應的current屬性,所以在current變化的時候,在引用到current的地方都會被通知到,然后渲染組件。

Vue.component('router-view', {render(h) {const obj = this.$router.$options.routes.find(el=>this.$router.current==el.path)return h(obj.component)}})

但是每次都要去遍歷循環字典,也不是很合理,我們可以優化一下,緩存一下path和route映射關系

路由嵌套

思路:參考源碼思路,給當前routerView深度標記,然后根據當前頁面路由獲取當前路由數組,其中包括一級和二級路由,然后使用depth獲取對應的組件,然后并渲染。

Vue.component('router-view', {render(h) {//標記當前router-view深度this.$vnode.data.routerView = truelet depth = 0let parent = this.$parentwhile (parent) {const vnodeData = parent.$vnode && parent.$vnode.dataif (vnodeData) {if (vnodeData.routerView) {//說明當前的parent是一個routerViewdepth++}}parent = parent.$parent}let component = nullconst route = this.$router.matched[depth]if (route) {component = route.component}return h(component)}})

此時我們不再使用current來做響應式,使用matched數組獲取匹配關系,VueRouter實例創建時調用match方法,獲取路由數組,并且在路由發生變化時重新獲取路由數組matched。

class VueRouter {constructor(options) {this.$options = options//聲明一個響應式current//渲染函數如果壓重復執行,必須依賴響應式數據// Vue.util.defineReactive(this,'current',window.location.hash.slice(1) || '/') //需要#后面的部分this.current = window.location.hash.slice(1) || '/' //初始值Vue.util.defineReactive(this, 'matched', [])// match方法可以遞歸的遍歷路由表獲取匹配關系的數組this.match()//監聽url變化window.addEventListener('hashchange', () => {this.current = window.location.hash.slice(1)this.matched=[]this.match()})}match(routes) {routes = routes || this.$options.routesconsole.log(routes);//遞歸遍歷路由表for (const route of routes) {if (this.current.indexOf(route.path)!=-1) {this.matched.push(route)if (route.children) {this.match(route.children)}return}}}
}

附完整代碼:

//vue-router插件
let Vue
// vueRouter是一個類,一個插件
class VueRouter {constructor(options) {this.$options = options//聲明一個響應式current//渲染函數如果壓重復執行,必須依賴響應式數據// Vue.util.defineReactive(this,'current',window.location.hash.slice(1) || '/') //需要#后面的部分this.current = window.location.hash.slice(1) || '/' //初始值Vue.util.defineReactive(this, 'matched', [])// match方法可以遞歸的遍歷路由表獲取匹配關系的數組this.match()//監聽url變化window.addEventListener('hashchange', () => {this.current = window.location.hash.slice(1)this.matched=[]this.match()})}match(routes) {routes = routes || this.$options.routes//遞歸遍歷路由表for (const route of routes) {if (this.current.indexOf(route.path)!=-1) {this.matched.push(route)if (route.children) {this.match(route.children)}return}}console.log(this.matched);}
}VueRouter.install = function (_Vue) {//保存引用Vue = _Vue//掛在一下vueRouter到vue原型//利用全局混入,全局執行代碼,在vue實例beforeCreate時獲取到router,因為在main.js中生成vue實例在VueRouter掛載到Vue之后,所以常規無法獲取到router,Vue.mixin({beforeCreate() {if (this.$options.router) { //避免每次實例創建都觸發,只有根實例上存在的才觸發。Vue.prototype.$router = this.$options.router}}})//聲明兩個全局組件,router-viewport,router-linkVue.component('router-link', {props: {to: {type: String,required: true}},//預編譯情況下,template是不能使用的,這里要使用render// template:'<a>123</a>'render(h) {// return <a href={'#'+this.to}>{this.$slots.default}</a> jsx語法也可以使用return h('a', {attrs: { href: "#" + this.to }}, this.$slots.default) //this.$slots.default 獲取內容}})Vue.component('router-view', {render(h) {//標記當前router-view深度this.$vnode.data.routerView = truelet depth = 0let parent = this.$parentwhile (parent) {const vnodeData = parent.$vnode && parent.$vnode.dataif (vnodeData) {if (vnodeData.routerView) {//說明當前的parent是一個routerViewdepth++}}parent = parent.$parent}let component = nullconsole.log(this.$router.matched);const route = this.$router.matched[depth]if (route) {component = route.component}return h(component)}})
}export default VueRouter
import Vue from 'vue'
// import VueRouter from 'vue-router'
import VueRouter from '@/krouter/kvue-router'
Vue.use(VueRouter)//執行install方法,router還未被創建
const routes = [{path: '/home',name: 'home',component: () => import('@/components/Home.vue')},{path: '/about',name: 'about',component: () => import('@/components/About.vue'),children: [{path: '/about/info',component: {render(h) {return h('div', 'info page')}}}]},
]const router = new VueRouter({routes
})
export default router

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/213421.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/213421.shtml
英文地址,請注明出處:http://en.pswp.cn/news/213421.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用Python提取PDF文件中指定頁面的內容

在日常工作和學習中&#xff0c;我們經常需要從PDF文件中提取特定頁面的內容。在本篇文章中&#xff0c;我們將介紹如何使用Python編程語言和兩個強大的庫——pymupdf和wxPython&#xff0c;來實現這個任務。 1. 準備工作 首先&#xff0c;確保你已經安裝了以下兩個Python庫&…

JavaScript深拷貝和淺拷貝

對于原始數據類型&#xff0c;并沒有深淺拷貝的區別&#xff0c;深淺拷貝都是對于引用數據類型而言&#xff0c;如果我們要賦值對象的所有屬性都是引用類型可以用淺拷貝 淺拷貝&#xff1a;只復制一層對象&#xff0c;當對象的屬性是引用類型時&#xff0c;實質復制的是其引用&…

【辦公軟件】Outlook啟動一直顯示“正在啟動”的解決方法

早上打開電腦Outlook2016以后&#xff0c;半個多小時了&#xff0c;一直顯示這個界面&#xff1a; 解決辦法 按WIN R鍵打開“運行”&#xff0c;輸入如下命令&#xff1a; outlook.exe /safe 然后點擊“確定” 這樣就進入了Outlook的安全模式。 點擊“文件”->“選項”-…

第6節:Vue3 調用函數

在Vue3中&#xff0c;你可以使用setup函數來調用函數。 <template><button click"handleClick">點擊我</button> </template><script> import { ref } from vue;export default {setup() {// 創建一個響應式的引用const count ref(0…

nbcio-vue下載安裝后運行報錯,diagram-js沒有安裝

更多nbcio-boot功能請看演示系統 gitee源代碼地址 后端代碼&#xff1a; https://gitee.com/nbacheng/nbcio-boot 前端代碼&#xff1a;https://gitee.com/nbacheng/nbcio-vue.git 在線演示&#xff08;包括H5&#xff09; &#xff1a; http://122.227.135.243:9888 根據…

047:vue加載循環倒計時 示例

第047個 查看專欄目錄: VUE ------ element UI 專欄目標 在vue和element UI聯合技術棧的操控下&#xff0c;本專欄提供行之有效的源代碼示例和信息點介紹&#xff0c;做到靈活運用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安裝、引用&#xff0c;模板使…

基于java web的網上書城系統的設計與實現論文

摘 要 隨著科學技術的飛速發展&#xff0c;各行各業都在努力與現代先進技術接軌&#xff0c;通過科技手段提高自身的優勢&#xff0c;商品交易當然也不能排除在外&#xff0c;隨著商品交易管理的不斷成熟&#xff0c;它徹底改變了過去傳統的經營管理方式&#xff0c;不僅使商品…

32、Bean的生產順序是由什么決定的?

Bean的生產順序是由什么決定的? BeanDefinition的注冊順序是有什么決定的? Bean在生產之前有個臨時狀態:BeanDefinition;存儲著bean的描述信息。由BeanDefinition決定著Bean的生產順序。會按照BeanDefinition的注冊順序來決定Bean的生產順序。因為所有的BeanDefinition存…

Lua字符串(包含任意字符,如中文)任意位置截取

常規的截取只需要lua自帶的api就可以解決問題:如 string.sub 但是當字符串之中含有中文或者符號的時候,這些接口就麻爪了,當然lua后續更新有可能支持,至少本少當前的Lua版本是不支持的。 廢話少說,直接上代碼和測試用例 -- 判斷utf8字符byte長度 function stringTool.ch…

統信UOS_麒麟KYLINOS上跨架構下載離線軟件包

原文鏈接&#xff1a;統信UOS/麒麟KYLINOS上跨架構下載離線軟件包 hello&#xff0c;大家好啊&#xff0c;今天給大家帶來一篇在統信UOS/麒麟KYLINOS上跨架構下載離線軟件包的實用教程。在我們的日常工作中&#xff0c;可能會遇到這樣的情況&#xff1a;需要為不同架構的設備下…

【總結】機器學習中的15種分類算法

目錄 一、機器學習中的分類算法 1.1 基礎分類算法 1.2 集成分類算法 1.3 其它分類算法&#xff1a; 二、各種機器學習分類算法的優缺點 分類算法也稱為模式識別&#xff0c;是一種機器學習算法&#xff0c;其主要目的是從數據中發現規律并將數據分成不同的類別。分類算法通…

鴻蒙OS應用開發之數據類型

前面學習了一個簡單的例子,這是多年來學習應用程序開發的經典路徑,在這里也是這種待遇,通過這樣的學習明白了一個簡單應用是怎么樣構成的,知道它是怎么運行輸出的。在這個基礎之上,你還是不會開發應用程序的,因為你還沒有學習鴻蒙應用的開發語言基礎,所以在這里要學習一…

nvue頁面用法uniapp

1.介紹 Nvue是一個基于weex改進的原生渲染引擎&#xff0c;它在某些方面要比vue更高性能&#xff0c;在app上使用更加流暢&#xff0c;但是缺點也很明顯&#xff0c;沒有足夠的api能力&#xff0c;語法限制太大&#xff0c;所以nvue適用于特定場景&#xff08;需要高性能的區域…

排序算法——桶排序/基數排序/計數排序

桶排序 是計數排序的升級版。它利用了函數的映射關系&#xff0c;高效與否的關鍵就在于這個映射函數的確定。桶排序 (Bucket sort)的工作的原理&#xff1a; 假設輸入數據服從均勻分布&#xff0c;將數據分到有限數量的桶里&#xff0c;每個桶再分別排序&#xff08;有可能再使…

pve(proxmox)宿主機奔潰無法進入系統,lxc容器和虛擬機遷移,無備份,硬盤未損壞,記錄數據找回過程及思考

pve的主機突然CPU滿載,然后遠程斷電后pve就無法啟動了,之前一直上面的虛擬機和容器也沒有備份,折騰了兩天總算找回來了記錄一下處理過程和思路,方便后續查找。 一、隱患分析 1.周四突然手欠,由于之前家里的pve主機老給我發郵件,提示我硬盤有問題,但可以正常使用,我從…

【使用apache snakeyaml 管理yml文件】

使用apache snakeyaml 管理yml文件 1. 一個Yaml工廠2.Yaml工具類3. 測試類4. 完成 &#xff01; OK 1. 一個Yaml工廠 public class YamlFactory {public static YamlUtil get(){return new YamlUtil();} }2.Yaml工具類 Slf4j public class YamlUtil {private Yaml yaml;publi…

想進階JAVA高級程序員嗎?多線程必學

??作者主頁&#xff1a;小虛竹 ??作者簡介&#xff1a;大家好,我是小虛竹。2022年度博客之星評選TOP 10&#x1f3c6;&#xff0c;Java領域優質創作者&#x1f3c6;&#xff0c;CSDN博客專家&#x1f3c6;&#xff0c;華為云享專家&#x1f3c6;&#xff0c;掘金年度人氣作…

【SpringSecurity】-- 認證、授權

文章目錄 SpringSecurity簡介快速入門1.準備工作1.2引入SpringSecurity 認證1.登錄校驗流程2.原理2.1SpringSecurity完整流程2.2認證流程詳解 3.解決問題3.1思路分析3.2準備工作3.3.實現3.3.1數據庫校驗用戶3.3.2密碼加密存儲3.3.3登錄接口3.3.4認證過濾器3.3.5退出登錄 授權1.…

輸入一組數據,以-1結束輸入[c]

我們新手寫題時總能看到題目中類似這樣的輸入 沒有給固定多少個數據&#xff0c;我們沒有辦法直接設置數組的元素個數&#xff0c;很糾結&#xff0c;下面我來提供一下本人的方法&#xff08;新手&#xff0c;看到有錯誤或者不好的地方歡迎大佬指出&#xff0c;糾正&#xff0…

c語言中的 *, , ** 符合代表什么意思

在C語言中&#xff0c;“&”主要有兩個用途。 取地址運算符&#xff1a;C語言中&#xff0c;"&"用來返回一個變量的內存地址。例如&#xff0c;假設我們定義了一個整數變量 int a 10;&#xff0c;那么 &a 就代表了這個變量所在的內存地址。 位運算符&a…