util.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. import { err } from '../helpers/warn';
  2. import { copyObject, parseQuery } from '../helpers/util';
  3. import { Global, route as mergeRoute } from '../helpers/config';
  4. /**
  5. * 触发指定生命钩子
  6. * @param {Array} funList //需要执行的方法列表
  7. * @param {Object} args //触发生命钩子传递的参数
  8. */
  9. export const callAppHook = function (funList = [], args) {
  10. for (let i = 0; i < funList.length; i += 1) {
  11. funList[i].call(this, args);
  12. }
  13. };
  14. /**
  15. * @param {Number} index //需要获取的页面下标 -2:表示获取最后一个即当前页面 -1:表示全部 -3:当前页面的前一个页面
  16. * @param {Boolean} all //是否获取全部的页面
  17. */
  18. export const getPages = function (index = -1, all) {
  19. const pages = getCurrentPages(all);
  20. if (index === -1) {
  21. return pages;
  22. }
  23. if (index === -2) {
  24. return pages[pages.length - 1];
  25. }
  26. if (index === -3) {
  27. return pages[pages.length - 2];
  28. }
  29. return pages[index];
  30. };
  31. /**
  32. * 验证当前页面是否为nvue页面
  33. * @param {Object} page 当前页面对象
  34. */
  35. export const isNvuePage = function (page) {
  36. const cstr = page.constructor.name;
  37. const pageType = {
  38. s: true,
  39. z: false,
  40. };
  41. return pageType[cstr];
  42. };
  43. /**
  44. * @param {Object} page //当前顶级页面对象
  45. * @param {Object} vim:? //是否获取 $vm 对象还是 $mp 对象
  46. */
  47. export const getPageVmOrMp = function (page, vim = true) {
  48. if (vim) {
  49. return page.$vm;
  50. }
  51. if (page.$vm.$mp) {
  52. return page.$vm.$mp;
  53. }
  54. if (isNvuePage(page)) { // nvue 页面
  55. return {
  56. page,
  57. query: page.__displayReporter.query,
  58. };
  59. }
  60. };
  61. /**
  62. * 获取 to 的配置参数
  63. * @param {Object} rule 当前跳转的规则
  64. */
  65. export const formatTo = function (finalRoute) {
  66. const route = copyObject(finalRoute.route);
  67. const { rule } = finalRoute;
  68. route.query = rule.query || rule.params || {};
  69. return route;
  70. };
  71. /**
  72. * 通过一个未知的路径或者名称 在路由表中查找指定路由表 并返回
  73. * @param {string} type //path 或者 name
  74. * @param {Object} routes //当前对象的所有路由表
  75. */
  76. export const pathOrNameToRoute = function (type, routes = Global.Router.CONFIG.routes) {
  77. const routesKeys = Object.keys(routes);
  78. for (let i = 0; i < routesKeys.length; i += 1) {
  79. const key = routesKeys[i];
  80. const item = routes[key];
  81. if (item.path === `/${type}`) {
  82. return mergeRoute(item); // 合并一下对象,主要是合并 query:{} 及 params:{}
  83. }
  84. if (item.path === type) {
  85. return mergeRoute(item); // 合并一下对象,主要是合并 query:{} 及 params:{}
  86. }
  87. if (item.name == type) {
  88. return mergeRoute(item); // 合并一下对象,主要是合并 query:{} 及 params:{}
  89. }
  90. }
  91. err(`当前 '${type}' 在路由表中没有找到匹配的 name 或者 path`);
  92. };
  93. /**
  94. * 统一格式话 路由传递的参数 看看是编码还是非编码 做相应的对策
  95. *
  96. * @param {Object} query 当前的路由参数
  97. * @param {Boolean} getter 是从页面获取 route 对象下的参数 还是编码后传输
  98. */
  99. export const getFormatQuery = function (query = {}) {
  100. if (Global.Router.CONFIG.encodeURI) {
  101. try {
  102. query = JSON.parse(decodeURIComponent(query.query || encodeURIComponent('{}')));
  103. } catch (e) {
  104. query = JSON.parse(query.query);
  105. }
  106. }
  107. return query;
  108. };
  109. /**
  110. * 获取 from 的配置参数 from 页面永远都是站在当前页面忘其它地方走 所以都是最后一个页面
  111. *
  112. * @param {Object} routes //当前对象的所有路由表
  113. */
  114. export const formatFrom = function (routes) {
  115. const topPage = getPages(-2);
  116. const { page, query } = getPageVmOrMp(topPage, false);
  117. const route = pathOrNameToRoute(page.route, routes); // 获取到当前路由表下的 route
  118. route.query = getFormatQuery(query); // 不管是编码传输还是非编码 最后都得在 to/from 中换成json对象
  119. return route;
  120. };
  121. /**
  122. *
  123. * 把用户的跳转路由规则格式化成uni-app可用的路由跳转规则
  124. *
  125. * @param {Object} rule //当前用户跳转的路由规则
  126. * @param {Object} routes //当前simple-router 下的路由表
  127. */
  128. export const ruleToUniNavInfo = function (rule, routes) {
  129. if (rule == null) {
  130. return err('当前跳转规则为空,请检查跳转代码');
  131. }
  132. // eslint-disable-next-line
  133. let [navType, route, query, animation] = ['path', null, {}, {}];
  134. if (rule.constructor === String) { // 是字符串类型 那当前就是路径啦
  135. route = pathOrNameToRoute(rule, routes); // 直接把 rule 当 path 传递 完事
  136. } else if (rule.constructor === Object) { // 对象类型 可以是 path 或者 name
  137. route = pathOrNameToRoute(rule.path || (navType = 'name', rule.name), routes); // 两则必有其一 报错自己处理
  138. query = rule.query || rule.params || {};
  139. animation = rule.animation || {};
  140. } else {
  141. return err('传的什么乱七八糟的类型?路由跳转规则只认字符串 \'path\' , 对象 \'path\' , 对象 \'name\' ');
  142. }
  143. animation = { ...Global.Router.CONFIG.APP.animation, ...route.animation || {}, ...animation }; // 合并多种方式声明的动画效果
  144. route.animation = animation; // 这才是最终的页面切换效果
  145. // 路径处理完后 开始格式化参数
  146. const uniRoute = parseQuery(route.path, query); // uni-app 需要的跳转规则
  147. return {
  148. rule,
  149. route,
  150. uniRoute,
  151. };
  152. };
  153. /**
  154. * 获取当前页面下的 Route 信息
  155. *
  156. * @param {Object} pages 获取页面对象集合
  157. * @param {Object} Vim 用户传递的当前页面对象
  158. */
  159. export const APPGetPageRoute = function (pages, Vim) {
  160. let [query, path] = [{}, ''];
  161. const page = pages[pages.length - 1]; // 获取到当前页面
  162. if (pages.length > 0) {
  163. query = getFormatQuery(page.options, true);
  164. path = page.route;
  165. } else if (Vim != null) {
  166. query = getFormatQuery(Vim.$mp.page.options, true);
  167. path = page.route;
  168. }
  169. const route = pathOrNameToRoute(path);
  170. route.query = query;
  171. return route;
  172. };
  173. /**
  174. * 获取当前页面下的 onBeforeBack 生命周期并执行
  175. *
  176. * @param {Object} args 当前返回页面时uni-app传递的参数
  177. */
  178. export const getPageOnBeforeBack = function (args) {
  179. return new Promise(async (resolve) => {
  180. const currPage = getPages(-2); // 获取到当前页面
  181. const { onBeforeBack } = currPage.$vm.$options;
  182. if (onBeforeBack != null && onBeforeBack.constructor === Function) {
  183. const isNext = await onBeforeBack.call(currPage.$vm, args);
  184. if (isNext === true) {
  185. return resolve(false);
  186. }
  187. }
  188. return resolve(true);
  189. });
  190. };
  191. /**
  192. * 断言当前页面是否可返回上一级
  193. * @param {Object} page 当前页面webview对象
  194. */
  195. export const assertCanBack = function (page) {
  196. const pageStyle = page.$getAppWebview().getStyle();
  197. if (pageStyle.titleNView != null && pageStyle.titleNView.autoBackButton) { // 只有处理有带返回按钮的页面
  198. return true;
  199. }
  200. // 两种情况 1.真的是顶级页面时 2.自定义头部
  201. const { $page } = page;
  202. if ($page && $page.meta.isQuit === false) { // 自定义头部 不是顶级页面
  203. return true;
  204. }
  205. return false; // 不可返回 真的是顶级页面时 返回就直接退出app了
  206. };