index.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /**
  2. * 版本号比较
  3. */
  4. const compareVersion = (v1, v2) => {
  5. v1 = v1.split('.')
  6. v2 = v2.split('.')
  7. const len = Math.max(v1.length, v2.length)
  8. while (v1.length < len) {
  9. v1.push('0')
  10. }
  11. while (v2.length < len) {
  12. v2.push('0')
  13. }
  14. for (let i = 0; i < len; i++) {
  15. const num1 = parseInt(v1[i])
  16. const num2 = parseInt(v2[i])
  17. if (num1 > num2) {
  18. return 1
  19. } else if (num1 < num2) {
  20. return -1
  21. }
  22. }
  23. return 0
  24. }
  25. Component({
  26. externalClasses: ['item-wrap-class'],
  27. options: {
  28. multipleSlots: true
  29. },
  30. properties: {
  31. extraNodes: { // 额外节点
  32. type: Array,
  33. value: []
  34. },
  35. listData: { // 数据源
  36. type: Array,
  37. value: []
  38. },
  39. columns: { // 列数
  40. type: Number,
  41. value: 1
  42. },
  43. topSize: { // 顶部固定高度
  44. type: Number,
  45. value: 0
  46. },
  47. bottomSize: { // 底部固定高度
  48. type: Number,
  49. value: 0
  50. },
  51. itemHeight: { // 每个 item 高度, 用于计算 item-wrap 高度
  52. type: Number,
  53. value: 0
  54. },
  55. scrollTop: { // 页面滚动高度
  56. type: Number,
  57. value: 0
  58. },
  59. searchVal:{ //搜索值
  60. type:String,
  61. value:''
  62. }
  63. },
  64. data: {
  65. /* 未渲染数据 */
  66. baseData: {},
  67. pageMetaSupport: false, // 当前版本是否支持 page-meta 标签
  68. platform: '', // 平台信息
  69. listWxs: [], // wxs 传回的最新 list 数据
  70. rows: 0, // 行数
  71. /* 渲染数据 */
  72. wrapStyle: '', // item-wrap 样式
  73. list: [], // 渲染数据列
  74. dragging: false,
  75. },
  76. methods: {
  77. vibrate() {
  78. if (this.data.platform !== "devtools") wx.vibrateShort();
  79. },
  80. pageScroll(e) {
  81. if (this.data.pageMetaSupport) {
  82. this.triggerEvent("scroll", {
  83. scrollTop: e.scrollTop
  84. });
  85. } else {
  86. wx.pageScrollTo({
  87. scrollTop: e.scrollTop,
  88. duration: 300
  89. });
  90. }
  91. },
  92. drag(e) {
  93. this.setData({
  94. dragging: e.dragging
  95. })
  96. },
  97. listChange(e) {
  98. this.data.listWxs = e.list;
  99. },
  100. itemClick(e) {
  101. let index = e.currentTarget.dataset.index;
  102. let item = this.data.listWxs[index];
  103. this.triggerEvent('click', {
  104. key: item.realKey,
  105. data: item.data,
  106. extra: e.detail
  107. });
  108. },
  109. /**
  110. * 初始化获取 dom 信息
  111. */
  112. initDom() {
  113. let {windowWidth, windowHeight, platform, SDKVersion} = wx.getSystemInfoSync();
  114. let remScale = (windowWidth || 375) / 375;
  115. this.data.pageMetaSupport = compareVersion(SDKVersion, '2.9.0') >= 0;
  116. this.data.platform = platform;
  117. let baseData = {};
  118. baseData.windowHeight = windowHeight;
  119. baseData.realTopSize = this.data.topSize * remScale / 2;
  120. baseData.realBottomSize = this.data.bottomSize * remScale / 2;
  121. baseData.columns = this.data.columns;
  122. baseData.rows = this.data.rows;
  123. const query = this.createSelectorQuery();
  124. query.select(".item").boundingClientRect();
  125. query.select(".item-wrap").boundingClientRect();
  126. query.exec((res) => {
  127. baseData.itemWidth = res[0].width;
  128. baseData.itemHeight = res[0].height;
  129. baseData.wrapLeft = res[1].left;
  130. baseData.wrapTop = res[1].top + this.data.scrollTop;
  131. this.setData({
  132. dragging: false,
  133. baseData
  134. });
  135. });
  136. },
  137. /**
  138. * column 改变时候需要清空 list, 以防页面溢出
  139. */
  140. columnChange() {
  141. this.setData({
  142. list: []
  143. })
  144. this.init();
  145. },
  146. /**
  147. * 初始化函数
  148. * {listData, topSize, bottomSize, itemHeight} 参数改变需要手动调用初始化方法
  149. */
  150. init() {
  151. // 初始必须为true以绑定wxs中的函数,
  152. this.setData({dragging: true});
  153. let delItem = (item, extraNode) => ({
  154. id: item.dragId,
  155. extraNode: extraNode,
  156. fixed: item.fixed,
  157. slot: item.slot,
  158. data: item
  159. });
  160. let {listData, extraNodes} = this.data;
  161. let _list = [], _before = [], _after = [], destBefore = [], destAfter = [];
  162. extraNodes.forEach((item, index) => {
  163. if (item.type === "before") {
  164. _before.push(delItem(item, true));
  165. } else if (item.type === "after") {
  166. _after.push(delItem(item, true));
  167. } else if (item.type === "destBefore") {
  168. destBefore.push(delItem(item, true));
  169. } else if (item.type === "destAfter") {
  170. destAfter.push(delItem(item, true));
  171. }
  172. });
  173. // 遍历数据源增加扩展项, 以用作排序使用
  174. listData.forEach((item, index) => {
  175. destBefore.forEach((i) => {
  176. if (i.data.destKey === index) _list.push(i);
  177. });
  178. _list.push(delItem(item, false));
  179. destAfter.forEach((i) => {
  180. if (i.data.destKey === index) _list.push(i);
  181. });
  182. });
  183. let i = 0, columns = this.data.columns;
  184. let list = (_before.concat(_list, _after) || []).map((item, index) => {
  185. item.realKey = item.extraNode ? -1 : i++; // 真实顺序
  186. item.sortKey = index; // 整体顺序
  187. item.tranX = `${(item.sortKey % columns) * 100}%`;
  188. item.tranY = `${Math.floor(item.sortKey / columns) * 100}%`;
  189. return item;
  190. });
  191. this.data.rows = Math.ceil(list.length / columns);
  192. this.setData({
  193. list,
  194. listWxs: list,
  195. wrapStyle: `height: ${this.data.rows * this.data.itemHeight}rpx`
  196. });
  197. if (list.length === 0) return;
  198. // 异步加载数据时候, 延迟执行 initDom 方法, 防止基础库 2.7.1 版本及以下无法正确获取 dom 信息
  199. setTimeout(() => this.initDom(), 0);
  200. }
  201. },
  202. ready() {
  203. this.init();
  204. }
  205. });