vue-router作為Vue官方三大套件之一,在日常開發中成為了不可或缺的存在,但是不管多麼
niubility
的框架或元件,在業務場景不斷髮生改變的同時,不可避免的會出現一些適用性上的問題,這就需要我們去擴充套件不同的使用場景,以達到業務上的最佳實踐。
vue-router使用姿勢
按照vue-router官方的使用文件中,我們在配置和使用vue-router的姿勢如下:
- 元件與路由的對映匹配
// router/index.js
const routes = [
{ path: '/home', component: Home },
{ path: '/about', component: About }
]
export default routes
複製程式碼
- 掛載router
// main.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import routes from './router/index.js'
const router = new VueRouter({
routes
});
new Vue({
el: '#app',
//讓vue知道我們的路由規則
router: router,
render: c => c(App),
})
複製程式碼
ok,現在我們就可以在我們的元件中通過this.$route
來操作路由相關屬性及方法了。簡直so easy!
vue-router的中心化問題
何為中心化?
談到中心化,我們想到比較多的可能就是區塊鏈
。那廣義上的中心化如何理解?簡單點說,就是在一個體系中某個節點要和另外的節點產生聯絡,就一定要通過特定的某個節點,這個節點就是一箇中心。
vue-router的中心化
剛講到中心化的概念,那我們可以拿上面vue-router實踐的例子來對照一下。
我們在router/index.js
中定義或載入所有的路由配置,那這個檔案就是這個專案當中唯一的引用路由的節點(中心)。那中心節點會存在什麼問題呢?
- 檔案衝突:尤其是在使用svn這種集中式版本控制服務,沒有分支的概念,全部依賴一個遠端中心倉庫。
- 釋出故障:試想多人同時修改同一個檔案,在釋出流程不是非常完善,且相互溝通不順暢的情況下,容易出現某個正在開發的需求被另一個同樣釋出中的需求帶上線了,但另一個需求的相關依賴並沒有上線。導致生產環境編譯錯誤從而引發線上故障。
下面我們用一個比較簡單的釋出模型來說明。
模擬開發場景:
- 2人同時開發一個專案。
- 2個需求分別新建了2個router配置。
- 現在2個需求都開發完了,準備繼續後續的測試->釋出流程。
PS: 上述的場景不一定發生,跟對應開發團隊的釋出流程相關。在開發流程比較完善的情況下是可以避免該問題的。
如何解決
- 模組化
- require.context
1. 模組化
可以將路由按業務模組劃分場景,對應模組下有一個獨立的入口檔案,儘可能保證相同業務需求不會出現路由檔案衝突的情況。
對應的載入路由的配置可以修改為
// moduleA/index.js
import routeA from './moduleA-xx'
import routeA2 from './moduleA-xx2'
// 在這裡擴充套件moduleA的路由配置
const routes = [].concat(routeA, routeA2)
export default routes
複製程式碼
// router/index.js
import moduleA from './moduleA/index'
import moduleB from './moduleB/index'
const routes = [].concat(moduleA, moduleB)
複製程式碼
2. require.context
官方文件的說明是require.context
使用 directory 路徑、includeSubdirs 選項和 filter 來指定一系列完整的依賴關係,便於更細粒度的控制模組引入。
文件地址:webpack.js.org/guides/depe…
簡單來說,通過require.context我們可以通過正則動態匹配並引入我們的依賴檔案,這樣我們不需要顯示的去載入我們的路由檔案,從而解耦router的入口檔案和對應route配置的依賴關係。在這裡我們通過它來實現我們的路由去中心化。
我們約定router目錄下所有的.js檔案預設都為route的配置檔案,通過require.context載入的程式碼如下。
// 載入router目錄下所有js檔案作為路由配置
let routes
let matches = require.context('./', true, /^\.\/[^/]+\/.+\.js$/)
matches.keys().forEach(key => {
routes = routes.concat(matches(key).default)
})
複製程式碼
這樣,以後新增或修改路由只需要按照約定在router目錄新建js檔案或修改其中的配置即可,router/index.js
不需要任何改動即可完成路由配置。
總結
在這裡我們總結下對於上述問題的一個解決思路,我們可以把中心化問題看成是一個依賴解耦的問題。那我們便可以用解耦的思路來解決中心化的問題,在上述解決方案中,我們用到了以下手段:
- 單一職責:模組化拆分路由配置。
- 依賴倒置:通過約定大於配置的方式將入口檔案與路由配置細節解耦,將路由配置的顯式載入過程抽象為通過
require.context
方式載入,具體的執行過程交由webpack在編譯構建時去分析,從而解除依賴。
關於解耦的問題,我覺得也是一個可以好好討論的點,有時間再和大家一起分享分享啦!感謝各位百忙之中抽出時間觀看!!!