123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- <template>
- <view>
- <view class="list">
- <view v-for="(keyItem, keyIndex) in renderList" :key="keyIndex" class="keyList">
- <view :id="'keyword' + keyItem.key" class="keyword">
- <text>{{ keyItem.key === 'AAA' ? '热门地区' : keyItem.key }}</text>
- </view>
- <view v-for="(item, index) in keyItem.list" :key="index" class="item b-b" @click="chooseCity(item)">
- <text>{{ item.label }}</text>
- </view>
- </view>
- </view>
- <view class="key-list column" @click.stop.prevent="stopPrevent">
- <view
- v-for="(item, index) in renderList"
- :key="index"
- :class="{active: index === keywordCurrent}"
- class="key-item"
- @click="onKeywordClick(index)"
- >
- <text>{{ item.key === 'AAA' ? '#' : item.key }}</text>
- </view>
- </view>
- <view :class="{show: keyChanged}" class="key-show center">
- <text>{{ keywordCurrentName }}</text>
- </view>
- </view>
- </template>
- <script>
- import getFirstLetter from './js/getFirstLetter.js'
- import cityData from './js/city'
- const _anchorList = [];
- let _onKeywordClicking = false;
- let _timer = 0;
- export default {
- data() {
- return {
- keyChanged: false,
- keywordCurrentName: '',
- keywordCurrent: 0, //当前索引
- renderList: [],
- list: [],
- }
- },
- onPageScroll(e) {
- if (_onKeywordClicking) {
- return;
- }
- const top = e.scrollTop;
- for (let i = 0; i < _anchorList.length; i++) {
- if (top > _anchorList[i]) {
- this.keywordCurrent = i;
- }
- }
- },
- watch: {
- keywordCurrent(val) {
- this.keywordCurrentName = this.renderList[val].key;
- if (_timer) {
- clearTimeout(_timer);
- }
- this.keyChanged = true;
- _timer = setTimeout(() => {
- this.keyChanged = false;
- }, 500)
- }
- },
- onLoad(options) {
- this.initList();
- },
- methods: {
- chooseCity(item) {
- const pages = getCurrentPages();
- const prePage = (pages[pages.length - 2]).$vm;
- prePage.city = item.label;
- prePage.searchList();
- uni.navigateBack();
- },
- //初始化列表
- initList() {
- const list = cityData;
- const tempData = {};
- list.forEach(item => {
- let key = getFirstLetter.getLetter(item.label).firstletter;
- if (!tempData[key]) {
- tempData[key] = [];
- }
- tempData[key].push(item);
- })
- //排序用
- const tempKeyList = [];
- for (let key in tempData) {
- tempKeyList.push(key);
- }
- tempKeyList.sort();
- const renderList = [];
- tempKeyList.forEach(keyword => {
- for (let key in tempData) {
- if (key == keyword) {
- renderList.push({
- key,
- list: tempData[key]
- })
- }
- }
- })
- this.renderList = renderList;
- //生成右侧索引
- setTimeout(() => {
- this.calcAnchor();
- }, 500)
- },
- //计算锚点高度
- calcAnchor() {
- const list = this.renderList;
- let size = {};
- const placeFillHeight = this.systemInfo.navigationBarHeight + this.systemInfo.statusBarHeight;
- list.forEach(async item => {
- let size = await this.getElSize('keyword' + item.key);
- item.top = size.top;
- _anchorList.push(size.top);
- })
- },
- //右侧索引点击
- onKeywordClick(index) {
- _onKeywordClicking = true;
- setTimeout(() => {
- _onKeywordClicking = false;
- }, 500)
- this.keywordCurrent = index;
- uni.pageScrollTo({
- scrollTop: this.renderList[index].top
- })
- },
- //获得元素的size
- getElSize(id) {
- return new Promise(res => {
- let el = uni.createSelectorQuery().select('#' + id);
- el.boundingClientRect(data => {
- res(data);
- }).exec();
- });
- }
- }
- }
- </script>
- <style>
- page {
- background-color: #f7f7f7;
- }
- </style>
- <style lang="scss" scoped>
- .key-show {
- position: fixed;
- left: 50%;
- top: 50%;
- z-index: 95;
- transform: translate(-50%, -50%);
- width: 80 rpx;
- height: 80 rpx;
- background-color: #2979ff;
- border-radius: 100 rpx;
- font-size: 40 rpx;
- font-weight: 600;
- color: #fff;
- opacity: 0;
- &.show {
- opacity: 1;
- }
- }
- .keyList {
- position: relative;
- .keyword {
- position: sticky;
- left: 0;
- top: var(--window-top);
- z-index: 95;
- padding-top: 6 rpx;
- padding-left: 30 rpx;
- width: 100%;
- height: 66 rpx;
- line-height: 60 rpx;
- font-size: 28 rpx;
- color: #333;
- font-weight: 700;
- background-color: #f7f7f7;
- }
- .item {
- padding-left: 30 rpx;
- line-height: 80 rpx;
- font-size: 28 rpx;
- color: #333;
- background-color: #fff;
- &:after {
- left: 30 rpx;
- }
- .cn-name {
- margin-left: 12 rpx;
- color: #666;
- }
- }
- }
- /* 右侧索引 */
- .key-list {
- position: fixed;
- right: 0;
- top: 50%;
- z-index: 96;
- padding-right: 20 rpx;
- padding-left: 40 rpx;
- transform: translateY(-50%);
- .key-item {
- width: 40 rpx;
- height: 40 rpx;
- margin-bottom: 2 rpx;
- text-align: center;
- line-height: 40 rpx;
- font-size: 26 rpx;
- color: #333;
- border-radius: 100 rpx;
- }
- .active {
- background-color: #2979ff;
- color: #fff;
- }
- }
- </style>
|