uni-simple-router

来源:https://www.cnblogs.com/xsk-walter/archive/2022/05/30/16304853.html
-Advertisement-
Play Games

uni-simple-router 專為uniapp打造的路由器,和uniapp深度集成 通配小程式、App和H5端 H5能完全使用vue-router開發 模塊化、查詢、通配符、路由參數 使 uni-app實現嵌套路由(僅H5端完全使用vue-router) uniapp用到了很多vue的api, ...


目錄

uni-simple-router
  • 專為uniapp打造的路由器,和uniapp深度集成
  • 通配小程式、App和H5端
  • H5能完全使用vue-router開發
  • 模塊化、查詢、通配符、路由參數
  • 使 uni-app實現嵌套路由(僅H5端完全使用vue-router)
  • uniapp用到了很多vue的api,但在路由管理的功能相對於vue-router還是比較欠缺的,比如全局導航守衛

官方文檔:https://hhyang.cn/v2/start/quickstart.html

一、快速上手
// 針對uniapp HBuilder創建的項目,非cli構建
// 1⃣ NPM 安裝
npm install uni-simple-router

// 2⃣ 初始化
npm install uni-read-pages // 配合vue.config.js自動讀取pages.json作為路由表的方式,源碼例如下:擴二

// 配置vue.config.js
const TransformPages = require('uni-read-pages')
const tfPages = new TransformPages()
module.exports = {
	configureWebpack: {
		plugins: [
		      new tfPages.webpack.DefinePlugin({
                      // 1⃣ 配置全局變數
                      // ROUTES: JSON.stringify(tfPages.routes) 
                      // 2⃣ includes 可自定義,解析pages.json路由配欄位的配置, 預設 ['path', 'name', 'aliasPath']
                        ROUTES: tfPages.webpack.DefinePlugin.runtimeValue(()=>{
                          const tf = new TransformPages({
                            includes:  ['path', 'name', 'aliasPath']
                          })
                          return JSON.stringify(tfPages.routes)
                        },true)
	              })
		]
	}
}

// /Applications/HBuilderX.app/Contents/HBuilderX/plugins/uniapp-cli/node_modules/webpack 我的webpack包路徑,在軟體contents包文件里軟體自帶的webpack
擴一:webpack插件之DefinePlugin
  • 允許創建一個 在編譯時可以配置的全局變數
  • 場景:區分不同開發模式處理
// 1⃣ 用法:每個傳進DefinePlugin的鍵值都是一個標誌或者多個用.連接起來的標識符
new webpack.DefinePlugin({
  PRODUCTION: JSON.stringify(true),
  BROWSER_SUPPRTS_HTML5: true,
  VERSION: JSON.stringify('abcde'),
  TWO: '1+1',
  'typeof window': JSON.stringify('object')
})
// 使用方式
console.log('Running App version', VERSION)
if(!BROWSER_SUPPRTS_HTML5) require("html5shiv")

// 2⃣ 功能標記 來作為一個flag標識啟用和禁用構建中的功能
new webpack.DefinePlugin({
  'SHOW_PRESSION': JOSN.string(true)
})

// 3⃣ 服務:可以配置不同環境下的url
new webpack.DefinePlugin({
  'DEV_URL': JSON.stringify(url_dev),
  'PRO_URL': JSON.stringify(url_pro)
})
擴二:uni-read-pages 如何獲取pages.json中的路由
// 依賴的源碼 - 通過node的path模塊獲取pages.json文件中的任何信息 (部分是個人註釋)
const path = require('path')
const CONFIG = { includes: ['path', 'aliasPath', 'name'] } // 預設獲取路由參數屬性
// process.cwd() 返回Node.js進程的當前工作目錄
// path.resolve(url1, 'abc') => url1/abc
const rootPath = path.resolve(process.cwd(), 'node_modules'); // 獲取根路徑

/** 解析絕對路徑
 * @param {Object} dir 
 */
function resolvePath(dir) {
	return path.resolve(rootPath, dir);
}
// 類
class TransformPages {
	constructor(config) {
    // 組合 自定義獲取配置屬性
		config = { ...CONFIG, ...config }; 
		this.CONFIG = config;
    
    // ↓本機文件路徑(HBuilderX包文件里自帶的webpack模塊路徑) /Applications/HBuilderX.app/Contents/HBuilderX/plugins/uniapp-cli/node_modules/webpack
		this.webpack = require(resolvePath('webpack'));
		this.uniPagesJSON = require(resolvePath('@dcloudio/uni-cli-shared/lib/pages.js'));
    
    // TODO: 根據CONFIG解析pages.json中的路由信息 和 小程式 分包下的路由
		this.routes = this.getPagesRoutes().concat(this.getNotMpRoutes());
	}
   // 獲取所有pages.json下的內容 返回json
	get pagesJson() {
		return this.uniPagesJSON.getPagesJson();
	}
	
  // 通過讀取pages.json文件 生成直接可用的routes
	getPagesRoutes(pages = this.pagesJson.pages, rootPath = null) {
		const routes = [];
		for (let i = 0; i < pages.length; i++) {
			const item = pages[i];
			const route = {};
			for (let j = 0; j < this.CONFIG.includes.length; j++) {
				const key = this.CONFIG.includes[j];
				let value = item[key];
				if (key === 'path') {
					value = rootPath ? `/${rootPath}/${value}` : `/${value}`
				}
				if (key === 'aliasPath' && i == 0 && rootPath == null) {
					route[key] = route[key] || '/'
				} else if (value !== undefined) {
					route[key] = value;
				}
			}
			routes.push(route);
		}
		return routes;
	}
  
	// 解析小程式分包路徑
	getNotMpRoutes() {
		const { subPackages } = this.pagesJson;
		let routes = [];
		if (subPackages == null || subPackages.length == 0) {
			return [];
		}
		for (let i = 0; i < subPackages.length; i++) {
			const subPages = subPackages[i].pages;
			const root = subPackages[i].root;
			const subRoutes = this.getPagesRoutes(subPages, root);
			routes = routes.concat(subRoutes)
		}
		return routes
	}
	/**
	 * 單條page對象解析
	 * @param {Object} pageCallback 
	 * @param {Object} subPageCallback
	 */
	parsePages(pageCallback, subPageCallback) {
		this.uniPagesJSON.parsePages(this.pagesJson, pageCallback, subPageCallback)
	}
}
module.exports = TransformPages
二、H5模式
2.1 路由配置
import {RouterMount,createRouter} from 'uni-simple-router';
const router = createRouter({
  // 路由配置
  routes: [
    {
      path: '/pages/index/index', // 必須和pages.json中相同
      extra: {
        pageStyle: { color: '#f00' }// 及其它自定義參數
      }
    }
  ]
})
// 組件中可以通過 this.$Route 查看路由元信息
2.2 完全使用vue-router開發 (H5端)
  • 嵌套路由時,若使用name方式跳轉,僅支持 this.$router.push({ name:  children1 })
// 使用 vue-router開發將會失去uniapp的生命周期
const router = createRouter({
  h5: {
    vueRouterDev: true, // 完全使用vue-router開發 預設是false
  },
  // 路由配置
  routes: [
    {
      path: '/',
     	name: 'home',
      component: () => import('@/common/router/home.vue'),
      // 嵌套路由(僅H5端),小程式端會重新頁面打開
      children: [
        {
          path: 'home/children1',
          name: 'children1',
          component: () => import('@/common/router/children1.vue')
        },
        {
          path: 'home/children2',
          name: 'children2',
          component: () => import('@/common/router/children2.vue')
        }
      ]
    }
  ]
})
2.3 H5 路由傳參
// 除vue-router外,美化url可以在基礎配置時,定義aliasPath變數,設置路由別名(瀏覽器地址欄展示名稱)
// 別名的設置,如果設置了別名,通過push路徑的方式,必須使用aliasPath的路徑才能生效
const router = createRouter({
  routes:[{
        name:'router1',
        //為了相容其他端,此時的path不能少,必須和 pages.json中的頁面路徑匹配
        path: "/pages/tabbar/tabbar-1/tabbar-1",    
        aliasPath: '/tabbar-1', 
    },]
});

// uni-simple-router路由跳轉
// aliasPath命名的路由 => name傳遞參數需 params
this.$Router.push({ name: 'detail', params: { id: 1 } })
// 帶查詢參數,變成 /home/id=1  => path 對應query,params失效
this.$Router.push({ path: '/pages/index/detail', query: { id: 1 }})
2.4 H5端路由捕獲所有路由或404路由
path:'*' // 通常用於客戶端404錯誤,如果是history模式,需要正確配置伺服器
path: '/detail-*'
// 路由的優先順序根據 定義的先後
2.5 路由懶載入
  • 打包構建應用時,Javascript包會變得非常大,影響頁面載入,把不同路由對應的組件分割成不同的代碼塊,然後當路由被訪問的時候才載入對應組件。

  •   const Foo = () => import('./Foo.vue')
      // 把組件按組分塊 使用 命名 chunk
      const Foo = () => import(/*webpackChunkName:"group-foo"*/ './Foo.vue')
      const Bar = () => import(/*webpackChunkName:"group-foo"*/ './Bar.vue')
    
三、小程式模式
  • 註:小程式系列無法攔截原生tabbar及原生導航返回,如需攔截使用自定義tabbar、header

  • 通過api進行切換時,像uni.switchTab()和this.$Router.pushTab()方法會觸發攔截的;僅底部原生tabbar進行切換時不觸發攔截

  • 強制觸發守衛:forceGuardEach(replaceAll, false) 每次調用api都會重新按流程觸發已經聲明的所有守衛

    • 小程式端預設:插件api跳轉、uni導航api跳轉和首屏載入
    • 使用路由守衛:通過點擊事件強制觸發、混入到onshow回調觸發
  • 跳轉路由鎖:animationDuration保留給redirection\push足夠時間,等切換完成頁面後才放行下次跳轉

    const router = createRouter({
      platform: process.env.VUE_APP_PLATFORM,
      // ① 路由鎖
      applet: {
        animationDuration: 300 // 預設300ms
        // animationDuration: 0 // 不精準 只捕捉跳轉api下的complete函數
      },
      // ②優雅解鎖 error.type: 0 表示 next(false)、1表示next(unknownType)、2表示加鎖狀態,禁止跳轉、3表示在獲取頁面棧時,頁面棧不夠level獲取
      routerErrorEach:(error, router) => {
        if (error.type === 3) {
          router.$lockStatus = false
        }
      },
      routes: [...ROUTES]
    })
    
四、路由跳轉
4.1 組件跳轉
  • vue-router中可以通過router-link組件進行頁面跳轉,uni-simple-router也提供了類似的組件,需要手動註冊

  •   // main.js
      import Link from './node_modules/uni-simple-router/dist/link.vue'
      Vue.component('Link', Link)
    
  •   // 通過path直接跳轉 並指定跳轉類型
      <Link to="/tabbar1" navType="pushTab">
      	<button type="primary">使用path對象跳轉</button>
      </Link>
    
4.2 編程式導航
  • 通過this.$Router獲取路由對象;push、pushTab、replace、back等api進行路由跳轉
  • 註:path搭配query參數、name搭配params參數
  • 導航使用方式同vue-router
五、跨平臺模式
5.1 提前享用生命周期
  • uniapp由於只用onLoad接受options參數、onShow不接受;傳遞深度對象參數時,需要先編碼再傳遞解碼

  •   // 動態改變參數 使 onLoad和onShow支持options
      const router = createRouter({
      	platform: process.env.VUE_APP_PLATFORM,  
      	routes: [...ROUTES],
      	beforeProxyHooks: {
      		onLoad(options, next){
      			next([router.currentRoute.query]);
      		},
      		onShow([options], next){
      			console.log(this);
      			const args=options||router.currentRoute.query;
      			next([args]);
      		},
      	},
      });
    
5.2 導航守衛
  • 全局前置守衛

    /**
    * to: Route 即將進入的目標
    * from: Route 當前導航正要離開的路由
    * next: Function 該方法的resolve鉤子函數必須調用,執行效果依賴next方法的調用參數
    * -- next()調用參數:管道中的下個鉤子; next(false)中斷當前導航;
    * -- next('/')/({path: '/'})跳轉到一個不同的地址。當前的導航被中斷,然後進行一個新的導航
    * -- next({delta: 2, NAVTYPE: 'back'}) 中斷當前導航,調用新的跳轉類型,同時返回兩層頁面
    **/
    router.beforeEach((to, from, next) => {
      // ...
      // 1⃣ next()
      // 2⃣ NAVTYPE定義跳轉方式,兩者相同非必填
      if (to.name == 'tabbar-5') {
            next({
                name: 'router4',
                params: {
                    msg: '我攔截了tab5並重定向到了路由4頁面上',
                },
                NAVTYPE: 'push'
            });
        } else{
        next();
      }
    })
    
  • 全局後置守衛

    // 不接受next函數也不改變導航本身
    router.afterEach((to,from) => {})
    
  • 路由獨享守衛

    // 路由配置上直接定義beforeEnter守衛
    const router = createRouter({
      routes: [{
        path: '/pages/home/index',
        beforeEnter:(to,from,next) => {
         // 參數同上全局前置守衛 
          next()
        }
      }]
    })
    
  • 組件內的守衛

    // 組件內配置beforeRouteLeave守衛 - 直接調用beforeRouteLeave方法
    export default {
      beforeRouteLeave(to, from, next) {
        // 導航離開該組件的對應路由時調用
        // 可以訪問組件實例this
        next()
      }
    }
    
六、路由守衛-模塊化
// 1⃣ 創建 router文件夾,模塊化配置 文件結構
|+------------------------+|
| router                   |
| |+--------------------+| |
| | modules              | |
| | |+----------------+| | |
| | | home.js          | | |
| | | index.js         | | |
| | |+----------------+| | |
| |+--------------------+| |
| index.js                 |
|+------------------------+|
// home.js
const home = [
  {
    path: '/pages/home/index',
    name: 'home'
  }
]
export default home
// modules下的index.js是一個模塊讀取
// ① require.context(directory, useSubdirectories, regExp) 具體詳情:如下擴三
const files = require.contxt('.',false,/.js$/)
const modules = []

files.keys().froEach(key => {
  if (key === './index.js') return
  const item = files(key).default
  modules.push(...item)
})

export default modules // 將所有模塊的路由模塊整合到一起, routes Array
// router下的index.js 路由守衛
import modules from './modules/index.js'
import Vue from 'vue'
import CreateRouter from 'uni-simple-router'
import store from '@/store/store.js'

Vue.use(CreateRouter)
//初始化
const router = new CreateRouter({
 APP: {
  holdTabbar: false //預設true
 },
 h5: {
  vueRouterDev: true, //完全使用vue-router開發 預設 false  
 },
 // 也可以 通過uni-read-pages來讀取pages.json文件的路由表,配合vue.config.js
 // router: [...ROUTES] // ROUTES是通過webpack的defaultPlugin編譯成全局變數,具體操作上文
 routes: [...modules] //路由表
});

//全局路由前置守衛
router.beforeEach((to, from, next) => {
 // 首先判斷是否存在路由信息
 //不存在就先調用介面得到數據
})
// 全局路由後置守衛
router.afterEach((to, from) => {})
export default router;
擴三、require.context用法
// require.context(directory, useSubdirectories, regExp)
// directory: 表示檢索的目錄
// useSubdirectories: 表示是否檢索子文件夾
// regExp: 匹配文件的正則表達式
// 返回值: resolve是一個函數,返回已解析請求的模塊ID; keys是一個函數,它返回上下文模塊可以處理的所有可能請求的數組;
// 使用場景:①用來組件內引入多個組件;②在main.js內引入大量公共組件;
// ①組件內引入多個組件 - webpack
const path = require('path')
const files = require.context('@/components/home', false, /\.vue$/) //值類型 ['./home.js', 'detail.js',...]
const modules = {}

files.keys().forEach(key => {
  const name = paths.basename(key, '.vue') // 去掉文件名的 .vue尾碼
  modules[name] = files(key).default || files(key)
})
// modules { home: '{module樣式路徑}', detail: '{}', ...  }
export default { 
  	...,
  	data() { return {}}, 
    components: modules
}
// ②在main.js內引入大量公共組件
import Vue from 'vue'
// 引入自定義組件
const requireComponents = require.context('../views/components',true,'/\.vue/')
// 遍歷出每個數組的路徑
requireComponents.keys().forEach(fileName => {
  const reqCom = requireComponents(fileName)
  // 獲取組件名
  const reqComName = reqCom.name || fileName.replace(/\.\/(.*)\.vue/, '$1')
  // 組件掛載
  Vue.components(reqComName, reqCom.default || reqCom)
})

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、PL/SQL簡介 1)SQL是一種標準化的結構化查詢語言,在資料庫領域有著廣泛的應用和重大影響。但是SQL並不能完成一個過程所能完成的任務,如某一個條件成立進行數據插入,否則不進行數據插入。 2)PL/SQL是Oracle公司對SQL語言的擴展,全面支持所有的SQL操作與數據類型。 3)PL/S ...
  • 卸載用戶價值的合理評估對制定相應的用戶召回策略具有重要意義。 HMS Core分析服務新版本支持查看用戶卸載前使用次數、崩潰次數等指標。通過這些數據,您可以更直觀地判斷已卸載人群粘性以及崩潰問題對用戶留存的直接影響,及時調優,減少用戶流失。 瞭解更多詳情>> 訪問華為開發者聯盟官網 獲取開髮指導文檔 ...
  • 原文地址:Android 實現開機自啟APP - Stars-One的雜貨小窩 公司有個項目,需要實現自啟動的功能,本來想著是設置桌面啟動器的方式去實現,但是設備是華為平板(EMUI系統),不允許設置第三方桌面 且監聽開機廣播也無效,本來以為沒法實現了,沒想到公司的另一款APP確實支持,於是便是研究 ...
  • 日常出行中,路徑規劃是很重要的部分。用戶想要去往某個地點,獲取到該地點的所有路徑,再根據預估出行時間自行選擇合適的路線,極大方便出行。平時生活中也存在大量使用場景,在出行類App中,根據乘客的目的地可以為用戶規劃合適出行路線和預計到達時間;便捷生活類App中,用戶可以搜索指定範圍內的周邊服務,查看去 ...
  • 一,引入中國地圖 <div id="chinaMap"></div> import china from 'echarts/map/js/china.js' export default { data() { return { myChart: {}, echarts:echarts, }; }, ...
  • Bootstrap Bootstrap是Twitter推出的一個用於前端開發的開源工具包。它由Twitter的設計師Mark Otto和Jacob Thornton合作開發,是一個CSS/HTML框架。目前,Bootstrap最新版本為4.4。 註意,Bootstrap有三個大版本分別是 v2、v3 ...
  • jQuery的操作標簽 文本操作 $("選擇符").html() // 讀取指定元素的內容,如果$()函數獲取了有多個元素,則提取第一個元素 $("選擇符").html(內容) // 修改內容,如果$()函數獲取了多個元素, 則批量修改內容 $("選擇符").text() // 效果同上,但是獲取的 ...
  • #snail-player-native 一個純原生代碼編寫的h5視頻播放器, 功能完善,基本滿足使用,僅供學習,禁止商用 演示 演示加速 Install 1. git clone https://github.com/snail-boy/snail-player-native.git 2. 拷貝l ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...