index.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var component_1 = require('../common/component');
  4. var touch_1 = require('../mixins/touch');
  5. var utils_1 = require('../common/utils');
  6. component_1.VantComponent({
  7. mixins: [touch_1.touch],
  8. classes: ['nav-class', 'tab-class', 'tab-active-class', 'line-class'],
  9. relation: {
  10. name: 'tab',
  11. type: 'descendant',
  12. current: 'tabs',
  13. linked: function (target) {
  14. target.index = this.children.length - 1;
  15. this.updateTabs();
  16. },
  17. unlinked: function () {
  18. this.children = this.children.map(function (child, index) {
  19. child.index = index;
  20. return child;
  21. });
  22. this.updateTabs();
  23. },
  24. },
  25. props: {
  26. color: {
  27. type: String,
  28. observer: 'setLine',
  29. },
  30. sticky: Boolean,
  31. animated: {
  32. type: Boolean,
  33. observer: function () {
  34. var _this = this;
  35. this.children.forEach(function (child, index) {
  36. return child.updateRender(index === _this.data.currentIndex, _this);
  37. });
  38. },
  39. },
  40. swipeable: Boolean,
  41. lineWidth: {
  42. type: [String, Number],
  43. value: -1,
  44. observer: 'setLine',
  45. },
  46. lineHeight: {
  47. type: [String, Number],
  48. value: -1,
  49. observer: 'setLine',
  50. },
  51. titleActiveColor: String,
  52. titleInactiveColor: String,
  53. active: {
  54. type: [String, Number],
  55. value: 0,
  56. observer: function (name) {
  57. if (name !== this.getCurrentName()) {
  58. this.setCurrentIndexByName(name);
  59. }
  60. },
  61. },
  62. type: {
  63. type: String,
  64. value: 'line',
  65. },
  66. border: {
  67. type: Boolean,
  68. value: true,
  69. },
  70. ellipsis: {
  71. type: Boolean,
  72. value: true,
  73. },
  74. duration: {
  75. type: Number,
  76. value: 0.3,
  77. },
  78. zIndex: {
  79. type: Number,
  80. value: 1,
  81. },
  82. swipeThreshold: {
  83. type: Number,
  84. value: 5,
  85. observer: function (value) {
  86. this.setData({
  87. scrollable: this.children.length > value || !this.data.ellipsis,
  88. });
  89. },
  90. },
  91. offsetTop: {
  92. type: Number,
  93. value: 0,
  94. },
  95. lazyRender: {
  96. type: Boolean,
  97. value: true,
  98. },
  99. },
  100. data: {
  101. tabs: [],
  102. lineStyle: '',
  103. scrollLeft: 0,
  104. scrollable: false,
  105. trackStyle: '',
  106. currentIndex: null,
  107. container: null,
  108. },
  109. mounted: function () {
  110. var _this = this;
  111. wx.nextTick(function () {
  112. _this.setLine(true);
  113. _this.scrollIntoView();
  114. });
  115. },
  116. methods: {
  117. updateContainer: function () {
  118. var _this = this;
  119. this.setData({
  120. container: function () {
  121. return _this.createSelectorQuery().select('.van-tabs');
  122. },
  123. });
  124. },
  125. updateTabs: function () {
  126. var _a = this,
  127. _b = _a.children,
  128. children = _b === void 0 ? [] : _b,
  129. data = _a.data;
  130. this.setData({
  131. tabs: children.map(function (child) {
  132. return child.data;
  133. }),
  134. scrollable:
  135. this.children.length > data.swipeThreshold || !data.ellipsis,
  136. });
  137. this.setCurrentIndexByName(this.getCurrentName() || data.active);
  138. },
  139. trigger: function (eventName, child) {
  140. var currentIndex = this.data.currentIndex;
  141. var currentChild = child || this.children[currentIndex];
  142. if (!utils_1.isDef(currentChild)) {
  143. return;
  144. }
  145. this.$emit(eventName, {
  146. index: currentChild.index,
  147. name: currentChild.getComputedName(),
  148. title: currentChild.data.title,
  149. });
  150. },
  151. onTap: function (event) {
  152. var _this = this;
  153. var index = event.currentTarget.dataset.index;
  154. var child = this.children[index];
  155. if (child.data.disabled) {
  156. this.trigger('disabled', child);
  157. } else {
  158. this.setCurrentIndex(index);
  159. wx.nextTick(function () {
  160. _this.trigger('click');
  161. });
  162. }
  163. },
  164. // correct the index of active tab
  165. setCurrentIndexByName: function (name) {
  166. var _a = this.children,
  167. children = _a === void 0 ? [] : _a;
  168. var matched = children.filter(function (child) {
  169. return child.getComputedName() === name;
  170. });
  171. if (matched.length) {
  172. this.setCurrentIndex(matched[0].index);
  173. }
  174. },
  175. setCurrentIndex: function (currentIndex) {
  176. var _this = this;
  177. var _a = this,
  178. data = _a.data,
  179. _b = _a.children,
  180. children = _b === void 0 ? [] : _b;
  181. if (
  182. !utils_1.isDef(currentIndex) ||
  183. currentIndex >= children.length ||
  184. currentIndex < 0
  185. ) {
  186. return;
  187. }
  188. children.forEach(function (item, index) {
  189. var active = index === currentIndex;
  190. if (active !== item.data.active || !item.inited) {
  191. item.updateRender(active, _this);
  192. }
  193. });
  194. if (currentIndex === data.currentIndex) {
  195. return;
  196. }
  197. var shouldEmitChange = data.currentIndex !== null;
  198. this.setData({ currentIndex: currentIndex });
  199. wx.nextTick(function () {
  200. _this.setLine();
  201. _this.scrollIntoView();
  202. _this.updateContainer();
  203. _this.trigger('input');
  204. if (shouldEmitChange) {
  205. _this.trigger('change');
  206. }
  207. });
  208. },
  209. getCurrentName: function () {
  210. var activeTab = this.children[this.data.currentIndex];
  211. if (activeTab) {
  212. return activeTab.getComputedName();
  213. }
  214. },
  215. setLine: function (skipTransition) {
  216. var _this = this;
  217. if (this.data.type !== 'line') {
  218. return;
  219. }
  220. var _a = this.data,
  221. color = _a.color,
  222. duration = _a.duration,
  223. currentIndex = _a.currentIndex,
  224. lineWidth = _a.lineWidth,
  225. lineHeight = _a.lineHeight;
  226. this.getRect('.van-tab', true).then(function (rects) {
  227. if (rects === void 0) {
  228. rects = [];
  229. }
  230. var rect = rects[currentIndex];
  231. if (rect == null) {
  232. return;
  233. }
  234. var width = lineWidth !== -1 ? lineWidth : rect.width / 2;
  235. var height =
  236. lineHeight !== -1
  237. ? 'height: ' +
  238. utils_1.addUnit(lineHeight) +
  239. '; border-radius: ' +
  240. utils_1.addUnit(lineHeight) +
  241. ';'
  242. : '';
  243. var left = rects.slice(0, currentIndex).reduce(function (prev, curr) {
  244. return prev + curr.width;
  245. }, 0);
  246. left += (rect.width - width) / 2;
  247. var transition = skipTransition
  248. ? ''
  249. : 'transition-duration: ' +
  250. duration +
  251. 's; -webkit-transition-duration: ' +
  252. duration +
  253. 's;';
  254. _this.setData({
  255. lineStyle:
  256. '\n ' +
  257. height +
  258. '\n width: ' +
  259. utils_1.addUnit(width) +
  260. ';\n background-color: ' +
  261. color +
  262. ';\n -webkit-transform: translateX(' +
  263. left +
  264. 'px);\n transform: translateX(' +
  265. left +
  266. 'px);\n ' +
  267. transition +
  268. '\n ',
  269. });
  270. });
  271. },
  272. // scroll active tab into view
  273. scrollIntoView: function () {
  274. var _this = this;
  275. var _a = this.data,
  276. currentIndex = _a.currentIndex,
  277. scrollable = _a.scrollable;
  278. if (!scrollable) {
  279. return;
  280. }
  281. Promise.all([
  282. this.getRect('.van-tab', true),
  283. this.getRect('.van-tabs__nav'),
  284. ]).then(function (_a) {
  285. var tabRects = _a[0],
  286. navRect = _a[1];
  287. var tabRect = tabRects[currentIndex];
  288. var offsetLeft = tabRects
  289. .slice(0, currentIndex)
  290. .reduce(function (prev, curr) {
  291. return prev + curr.width;
  292. }, 0);
  293. _this.setData({
  294. scrollLeft: offsetLeft - (navRect.width - tabRect.width) / 2,
  295. });
  296. });
  297. },
  298. onTouchScroll: function (event) {
  299. this.$emit('scroll', event.detail);
  300. },
  301. onTouchStart: function (event) {
  302. if (!this.data.swipeable) return;
  303. this.touchStart(event);
  304. },
  305. onTouchMove: function (event) {
  306. if (!this.data.swipeable) return;
  307. this.touchMove(event);
  308. },
  309. // watch swipe touch end
  310. onTouchEnd: function () {
  311. if (!this.data.swipeable) return;
  312. var _a = this,
  313. direction = _a.direction,
  314. deltaX = _a.deltaX,
  315. offsetX = _a.offsetX;
  316. var minSwipeDistance = 50;
  317. if (direction === 'horizontal' && offsetX >= minSwipeDistance) {
  318. var index = this.getAvaiableTab(deltaX);
  319. if (index !== -1) {
  320. this.setCurrentIndex(index);
  321. }
  322. }
  323. },
  324. getAvaiableTab: function (direction) {
  325. var _a = this.data,
  326. tabs = _a.tabs,
  327. currentIndex = _a.currentIndex;
  328. var step = direction > 0 ? -1 : 1;
  329. for (
  330. var i = step;
  331. currentIndex + i < tabs.length && currentIndex + i >= 0;
  332. i += step
  333. ) {
  334. var index = currentIndex + i;
  335. if (
  336. index >= 0 &&
  337. index < tabs.length &&
  338. tabs[index] &&
  339. !tabs[index].disabled
  340. ) {
  341. return index;
  342. }
  343. }
  344. return -1;
  345. },
  346. },
  347. });