index.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import { VantComponent } from '../common/component';
  2. import { addUnit } from '../common/utils';
  3. let ARRAY = [];
  4. VantComponent({
  5. field: true,
  6. relation: {
  7. name: 'dropdown-item',
  8. type: 'descendant',
  9. linked(target) {
  10. this.children = this.children || [];
  11. // 透传 props 给 dropdown-item
  12. const { overlay, duration, activeColor, closeOnClickOverlay, direction } = this.data;
  13. this.updateChildData(target, {
  14. overlay,
  15. duration,
  16. activeColor,
  17. closeOnClickOverlay,
  18. direction,
  19. childIndex: this.children.length
  20. });
  21. this.children.push(target);
  22. // 收集 dorpdown-item 的 data 挂在 data 上
  23. target &&
  24. this.setData({
  25. itemListData: this.data.itemListData.concat([target.data])
  26. });
  27. },
  28. unlinked(target) {
  29. this.children = this.children.filter((child) => child !== target);
  30. }
  31. },
  32. props: {
  33. activeColor: String,
  34. overlay: {
  35. type: Boolean,
  36. value: true
  37. },
  38. zIndex: {
  39. type: Number,
  40. value: 10
  41. },
  42. duration: {
  43. type: Number,
  44. value: 200
  45. },
  46. direction: {
  47. type: String,
  48. value: 'down'
  49. },
  50. closeOnClickOverlay: {
  51. type: Boolean,
  52. value: true
  53. },
  54. closeOnClickOutside: {
  55. type: Boolean,
  56. value: true
  57. }
  58. },
  59. data: {
  60. itemListData: []
  61. },
  62. created() {
  63. ARRAY.push(this);
  64. },
  65. destroyed() {
  66. ARRAY = ARRAY.filter(item => item !== this);
  67. },
  68. methods: {
  69. updateChildData(childItem, newData, needRefreshList = false) {
  70. childItem.setData(newData);
  71. if (needRefreshList) {
  72. // dropdown-item data 更新,涉及到 title 的展示,触发模板更新
  73. this.setData({ itemListData: this.data.itemListData });
  74. }
  75. },
  76. toggleItem(active) {
  77. this.children.forEach((item, index) => {
  78. const { showPopup } = item.data;
  79. if (index === active) {
  80. this.toggleChildItem(item);
  81. }
  82. else if (showPopup) {
  83. this.toggleChildItem(item, false, { immediate: true });
  84. }
  85. });
  86. },
  87. toggleChildItem(childItem, show, options = {}) {
  88. const { showPopup, duration } = childItem.data;
  89. if (show === undefined)
  90. show = !showPopup;
  91. if (show === showPopup) {
  92. return;
  93. }
  94. const newChildData = { transition: !options.immediate, showPopup: show };
  95. if (!show) {
  96. const time = options.immediate ? 0 : duration;
  97. this.updateChildData(childItem, Object.assign({}, newChildData), true);
  98. setTimeout(() => {
  99. this.updateChildData(childItem, { showWrapper: false }, true);
  100. }, time);
  101. return;
  102. }
  103. this.getChildWrapperStyle().then((wrapperStyle = '') => {
  104. this.updateChildData(childItem, Object.assign(Object.assign({}, newChildData), { wrapperStyle, showWrapper: true }), true);
  105. });
  106. },
  107. close() {
  108. this.children.forEach((item) => {
  109. this.toggleChildItem(item, false, { immediate: true });
  110. });
  111. },
  112. getChildWrapperStyle() {
  113. const { windowHeight } = wx.getSystemInfoSync();
  114. const { zIndex, direction } = this.data;
  115. let offset = 0;
  116. return this.getRect('.van-dropdown-menu').then(rect => {
  117. const { top = 0, bottom = 0 } = rect;
  118. if (direction === 'down') {
  119. offset = bottom;
  120. }
  121. else {
  122. offset = windowHeight - top;
  123. }
  124. let wrapperStyle = `z-index: ${zIndex};`;
  125. if (direction === 'down') {
  126. wrapperStyle += `top: ${addUnit(offset)};`;
  127. }
  128. else {
  129. wrapperStyle += `bottom: ${addUnit(offset)};`;
  130. }
  131. return Promise.resolve(wrapperStyle);
  132. });
  133. },
  134. onTitleTap(event) {
  135. // item ---> dropdown-item
  136. const { item, index } = event.currentTarget.dataset;
  137. if (!item.disabled) {
  138. // menuItem ---> dropdown-menu
  139. ARRAY.forEach(menuItem => {
  140. if (menuItem && menuItem.data.closeOnClickOutside && menuItem !== this) {
  141. menuItem.close();
  142. }
  143. });
  144. this.toggleItem(index);
  145. }
  146. }
  147. }
  148. });