学员端小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
3.7 KiB

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