route.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /**
  2. * 路由跳转方法,该方法相对于直接使用uni.xxx的好处是使用更加简单快捷
  3. * 并且带有路由拦截功能
  4. */
  5. import { queryParams, deepMerge, page } from '@/uni_modules/uv-ui-tools/libs/function/index.js'
  6. class Router {
  7. constructor() {
  8. // 原始属性定义
  9. this.config = {
  10. type: 'navigateTo',
  11. url: '',
  12. delta: 1, // navigateBack页面后退时,回退的层数
  13. params: {}, // 传递的参数
  14. animationType: 'pop-in', // 窗口动画,只在APP有效
  15. animationDuration: 300, // 窗口动画持续时间,单位毫秒,只在APP有效
  16. intercept: false ,// 是否需要拦截
  17. events: {} // 页面间通信接口,用于监听被打开页面发送到当前页面的数据。hbuilderx 2.8.9+ 开始支持。
  18. }
  19. // 因为route方法是需要对外赋值给另外的对象使用,同时route内部有使用this,会导致route失去上下文
  20. // 这里在构造函数中进行this绑定
  21. this.route = this.route.bind(this)
  22. }
  23. // 判断url前面是否有"/",如果没有则加上,否则无法跳转
  24. addRootPath(url) {
  25. return url[0] === '/' ? url : `/${url}`
  26. }
  27. // 整合路由参数
  28. mixinParam(url, params) {
  29. url = url && this.addRootPath(url)
  30. // 使用正则匹配,主要依据是判断是否有"/","?","="等,如“/page/index/index?name=mary"
  31. // 如果有url中有get参数,转换后无需带上"?"
  32. let query = ''
  33. if (/.*\/.*\?.*=.*/.test(url)) {
  34. // object对象转为get类型的参数
  35. query = queryParams(params, false)
  36. // 因为已有get参数,所以后面拼接的参数需要带上"&"隔开
  37. return url += `&${query}`
  38. }
  39. // 直接拼接参数,因为此处url中没有后面的query参数,也就没有"?/&"之类的符号
  40. query = queryParams(params)
  41. return url += query
  42. }
  43. // 对外的方法名称
  44. async route(options = {}, params = {}) {
  45. // 合并用户的配置和内部的默认配置
  46. let mergeConfig = {}
  47. if (typeof options === 'string') {
  48. // 如果options为字符串,则为route(url, params)的形式
  49. mergeConfig.url = this.mixinParam(options, params)
  50. mergeConfig.type = 'navigateTo'
  51. } else {
  52. mergeConfig = deepMerge(this.config, options)
  53. // 否则正常使用mergeConfig中的url和params进行拼接
  54. mergeConfig.url = this.mixinParam(options.url, options.params)
  55. }
  56. // 如果本次跳转的路径和本页面路径一致,不执行跳转,防止用户快速点击跳转按钮,造成多次跳转同一个页面的问题
  57. if (mergeConfig.url === page()) return
  58. if (params.intercept) {
  59. mergeConfig.intercept = params.intercept
  60. }
  61. // params参数也带给拦截器
  62. mergeConfig.params = params
  63. // 合并内外部参数
  64. mergeConfig = deepMerge(this.config, mergeConfig)
  65. // 判断用户是否定义了拦截器
  66. if (typeof mergeConfig.intercept === 'function') {
  67. // 定一个promise,根据用户执行resolve(true)或者resolve(false)来决定是否进行路由跳转
  68. const isNext = await new Promise((resolve, reject) => {
  69. mergeConfig.intercept(mergeConfig, resolve)
  70. })
  71. // 如果isNext为true,则执行路由跳转
  72. isNext && this.openPage(mergeConfig)
  73. } else {
  74. this.openPage(mergeConfig)
  75. }
  76. }
  77. // 执行路由跳转
  78. openPage(config) {
  79. // 解构参数
  80. const {
  81. url,
  82. type,
  83. delta,
  84. animationType,
  85. animationDuration,
  86. events
  87. } = config
  88. if (config.type == 'navigateTo' || config.type == 'to') {
  89. uni.navigateTo({
  90. url,
  91. animationType,
  92. animationDuration,
  93. events
  94. })
  95. }
  96. if (config.type == 'redirectTo' || config.type == 'redirect') {
  97. uni.redirectTo({
  98. url
  99. })
  100. }
  101. if (config.type == 'switchTab' || config.type == 'tab') {
  102. uni.switchTab({
  103. url
  104. })
  105. }
  106. if (config.type == 'reLaunch' || config.type == 'launch') {
  107. uni.reLaunch({
  108. url
  109. })
  110. }
  111. if (config.type == 'navigateBack' || config.type == 'back') {
  112. uni.navigateBack({
  113. delta
  114. })
  115. }
  116. }
  117. }
  118. export default (new Router()).route