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.

242 lines
5.1 KiB

3 years ago
  1. <template>
  2. <view>
  3. <view class="list">
  4. <view class="keyList" v-for="(keyItem, keyIndex) in renderList" :key="keyIndex">
  5. <view :id="'keyword' + keyItem.key" class="keyword">
  6. <text>{{ keyItem.key === 'AAA' ? '热门地区' : keyItem.key }}</text>
  7. </view>
  8. <view class="item b-b" v-for="(item, index) in keyItem.list" :key="index" @click="chooseCity(item)">
  9. <text>{{ item.label }}</text>
  10. </view>
  11. </view>
  12. </view>
  13. <view class="key-list column" @click.stop.prevent="stopPrevent">
  14. <view
  15. class="key-item"
  16. :class="{active: index === keywordCurrent}"
  17. v-for="(item, index) in renderList"
  18. :key="index"
  19. @click="onKeywordClick(index)"
  20. >
  21. <text>{{ item.key === 'AAA' ? '#' : item.key }}</text>
  22. </view>
  23. </view>
  24. <view class="key-show center" :class="{show: keyChanged}">
  25. <text>{{ keywordCurrentName }}</text>
  26. </view>
  27. </view>
  28. </template>
  29. <script>
  30. import getFirstLetter from './js/getFirstLetter.js'
  31. import cityData from './js/city'
  32. const _anchorList = [];
  33. let _onKeywordClicking = false;
  34. let _timer = 0;
  35. export default {
  36. data() {
  37. return {
  38. keyChanged: false,
  39. keywordCurrentName: '',
  40. keywordCurrent: 0, //当前索引
  41. renderList: [],
  42. list: [],
  43. }
  44. },
  45. onPageScroll(e) {
  46. if (_onKeywordClicking) {
  47. return;
  48. }
  49. const top = e.scrollTop;
  50. for (let i = 0; i < _anchorList.length; i++) {
  51. if (top > _anchorList[i]) {
  52. this.keywordCurrent = i;
  53. }
  54. }
  55. },
  56. watch: {
  57. keywordCurrent(val) {
  58. this.keywordCurrentName = this.renderList[val].key;
  59. if (_timer) {
  60. clearTimeout(_timer);
  61. }
  62. this.keyChanged = true;
  63. _timer = setTimeout(() => {
  64. this.keyChanged = false;
  65. }, 500)
  66. }
  67. },
  68. onLoad(options) {
  69. this.initList();
  70. },
  71. methods: {
  72. chooseCity(item){
  73. const pages = getCurrentPages();
  74. const prePage = (pages[pages.length - 2]).$vm;
  75. prePage.city = item.label;
  76. prePage.searchList();
  77. uni.navigateBack();
  78. },
  79. //初始化列表
  80. initList() {
  81. const list = cityData;
  82. const tempData = {};
  83. list.forEach(item => {
  84. let key = getFirstLetter.getLetter(item.label).firstletter;
  85. if (!tempData[key]) {
  86. tempData[key] = [];
  87. }
  88. tempData[key].push(item);
  89. })
  90. //排序用
  91. const tempKeyList = [];
  92. for (let key in tempData) {
  93. tempKeyList.push(key);
  94. }
  95. tempKeyList.sort();
  96. const renderList = [];
  97. tempKeyList.forEach(keyword => {
  98. for (let key in tempData) {
  99. if (key == keyword) {
  100. renderList.push({
  101. key,
  102. list: tempData[key]
  103. })
  104. }
  105. }
  106. })
  107. this.renderList = renderList;
  108. //生成右侧索引
  109. setTimeout(() => {
  110. this.calcAnchor();
  111. }, 500)
  112. },
  113. //计算锚点高度
  114. calcAnchor() {
  115. const list = this.renderList;
  116. let size = {};
  117. const placeFillHeight = this.systemInfo.navigationBarHeight + this.systemInfo.statusBarHeight;
  118. list.forEach(async item => {
  119. let size = await this.getElSize('keyword' + item.key);
  120. item.top = size.top;
  121. _anchorList.push(size.top);
  122. })
  123. },
  124. //右侧索引点击
  125. onKeywordClick(index) {
  126. _onKeywordClicking = true;
  127. setTimeout(() => {
  128. _onKeywordClicking = false;
  129. }, 500)
  130. this.keywordCurrent = index;
  131. uni.pageScrollTo({
  132. scrollTop: this.renderList[index].top
  133. })
  134. },
  135. //获得元素的size
  136. getElSize(id) {
  137. return new Promise(res => {
  138. let el = uni.createSelectorQuery().select('#' + id);
  139. el.boundingClientRect(data => {
  140. res(data);
  141. }).exec();
  142. });
  143. }
  144. }
  145. }
  146. </script>
  147. <style>
  148. page {
  149. background-color: #f7f7f7;
  150. }
  151. </style>
  152. <style scoped lang="scss">
  153. .key-show {
  154. position: fixed;
  155. left: 50%;
  156. top: 50%;
  157. z-index: 95;
  158. transform: translate(-50%, -50%);
  159. width: 80rpx;
  160. height: 80rpx;
  161. background-color: $base-color;
  162. border-radius: 100rpx;
  163. font-size: 40rpx;
  164. font-weight: 600;
  165. color: #fff;
  166. opacity: 0;
  167. &.show {
  168. opacity: 1;
  169. }
  170. }
  171. .keyList {
  172. position: relative;
  173. .keyword {
  174. position: sticky;
  175. left: 0;
  176. top: var(--window-top);
  177. z-index: 95;
  178. padding-top: 6rpx;
  179. padding-left: 30rpx;
  180. width: 100%;
  181. height: 66rpx;
  182. line-height: 60rpx;
  183. font-size: 28rpx;
  184. color: #333;
  185. font-weight: 700;
  186. background-color: #f7f7f7;
  187. }
  188. .item {
  189. padding-left: 30rpx;
  190. line-height: 80rpx;
  191. font-size: 28rpx;
  192. color: #333;
  193. background-color: #fff;
  194. &:after {
  195. left: 30rpx;
  196. }
  197. .cn-name {
  198. margin-left: 12rpx;
  199. color: #666;
  200. }
  201. }
  202. }
  203. /* 右侧索引 */
  204. .key-list {
  205. position: fixed;
  206. right: 0;
  207. top: 50%;
  208. z-index: 96;
  209. padding-right: 20rpx;
  210. padding-left: 40rpx;
  211. transform: translateY(-50%);
  212. .key-item {
  213. width: 40rpx;
  214. height: 40rpx;
  215. margin-bottom: 2rpx;
  216. text-align: center;
  217. line-height: 40rpx;
  218. font-size: 26rpx;
  219. color: #333;
  220. border-radius: 100rpx;
  221. }
  222. .active {
  223. background-color: $base-color;
  224. color: #fff;
  225. }
  226. }
  227. </style>