版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shelbyandfxj/article/details/83152158
<template>
<div style="height: 100%;">
<div class="search-div">
<i class="search-icon"></i>
<!--<input type="search" placeholder=""/>-->
<input placeholder="" @input="handleInput"/>
</div>
<!--搜索结果-->
<div class="search-result-div" v-if="hasResult">
<ul>
<li v-for="city in searchResultList" :id="city.id" @click="handleSelectCity(city)">{{city.name}}</li>
</ul>
</div>
<div class="no-result" v-if="hasNoResult">抱歉,未找到你要搜索的内容</div>
<div
ref="cityContainer"
class="swiper-container"
style="height: calc(100% - 70px); overflow: hidden;" // overflow:hidden避免滑动时溢出
v-if="!hasResult && !hasNoResult"
>
<div
ref="cityWrapper"
class="swiper-wrapper"
>
<div class="cur-city-div block-list swiper-slide">
<p>当前</p>
<div class="grid">
<div class="grid-cell">
<p class="poi-text cur-city-text">
{{curCityName}}
</p>
</div>
</div>
</div>
<div class="pop-use-div block-list swiper-slide">
<p>热点</p>
<div class="grid">
<div class="grid-cell" v-for="(item) in popCityList" @click="changeCity(item)">
<p class="poi-text" :id="item.id">
<!--<a class="loc-icon" :class="{'active':id == item.id}"></a>-->{{item.name}}</p>
</div>
</div>
</div>
<!--列表-->
<div class="all-city-div block-list swiper-slide" v-for="cityList in allCityList" :id="cityList.id">
<p class="city-list-anchor">{{cityList.name}}</p>
<div class="city-block-div">
<ul>
<li v-for="city in cityList.data" @click="changeCity(city)">{{city.name}}</li>
</ul>
</div>
</div>
</div>
</div>
<div class="city-letter-div"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
v-if="!hasResult && !hasNoResult"
>
<ul ref="cityLetterUl">
<li v-for="letter in letterList">{{letter.name}}</li>
</ul>
</div>
<div class="city-letter-select" v-if="letterClick">
<p>{{letterName}}</p>
</div>
</div>
</template>
<script>
import Swiper from 'swiper';
export default {
name: 'switchCity',
components: {},
data() {
return {
swiper: null,
searchVal: '',
letterClick: false,
letterName: '',
locCityName: '',
hasResult: false,
hasNoResult: false,
startY: 0, // 初始位置
startIndex: 0, // 初始的letterIndex
disY: 0, // 滑动距离
searchResultList: [], // 搜索结果
allCityList: [{
id: 2,
name: 'A',
data: [
{
index: 'A',
name: '鞍山市',
id: 'as'
},
{
index: 'A',
name: '安庆市',
id: '86032424'
},
{
index: 'A',
name: '安阳市',
id: 'ay'
},
{
index: 'A',
name: '阿拉善盟',
id: 'alsm'
},
{
index: 'A',
name: '阿坝州',
id: 'abz'
},
{
index: 'A',
name: '安顺市',
id: 'ass'
},
{
index: 'A',
name: '阿里地区',
id: 'aldq'
},
{
index: 'A',
name: '安康市',
id: 'aks'
},
{
index: 'A',
name: '阿克苏地区',
id: 'aksdq'
}
]
}, {
id: 3,
name: 'B',
data: [
{
index: 'B',
name: '鞍山市',
id: 'as'
},
{
index: 'B',
name: '安庆市',
id: 'aq'
},
{
index: 'B',
name: '安阳市',
id: 'ay'
},
{
index: 'B',
name: '阿拉善盟',
id: 'alsm'
},
{
index: 'B',
name: '阿坝州',
id: 'abz'
},
{
index: 'B',
name: '安顺市',
id: 'ass'
},
{
index: 'B',
name: '阿里地区',
id: 'aldq'
},
{
index: 'B',
name: '安康市',
id: 'aks'
},
{
index: 'B',
name: '安康市',
id: 'aks'
},
{
index: 'B',
name: '阿克苏地区',
id: 'aksdq'
}
]
}],
letterList: [
{
name: '当前',
id: '0'
},
{
name: '热门',
id: '1'
},
{
name: 'A',
id: '2'
},
{
name: 'B',
id: '3'
},
{
name: 'C',
id: '4'
},
{
name: 'D',
id: '5'
},
{
name: 'E',
id: 'E'
},
{
name: 'F',
id: 'F'
},
{
name: 'G',
id: 'G'
},
{
name: 'H',
id: 'H'
},
{
name: 'I',
id: 'I'
},
{
name: 'J',
id: 'J'
},
{
name: 'K',
id: 'K'
},
{
name: 'L',
id: 'L'
},
{
name: 'M',
id: 'M'
},
{
name: 'N',
id: 'N'
},
{
name: 'O',
id: 'O'
},
{
name: 'P',
id: 'P'
},
{
name: 'Q',
id: 'Q'
},
{
name: 'R',
id: 'R'
},
{
name: 'S',
id: 'S'
},
{
name: 'T',
id: 'T'
},
{
name: 'U',
id: 'U'
},
{
name: 'V',
id: 'V'
},
{
name: 'W',
id: 'W'
},
{
name: 'X',
id: 'X'
},
{
name: 'Y',
id: 'Y'
},
{
name: 'Z',
id: 'Z'
}
]
}
},
mounted() {
this._initSwiper();
for (let i = 0; i < this.commonCityList.length; i++) {
if (this.$store.state.userCurBuildId === this.commonCityList[i].buildId) {
this.locCityName = this.commonCityList[i].name;
}
}
// this.locCityName = ;
},
computed: {
buildId() {
return this.$store.state.showCityId;
},
commonCityList() {
return this.$store.state.commonCityList;
},
popCityList() {
return this.$store.state.commonCityList;
},
curCityName() {
return this.$store.state.showCityName;
},
isLocate() {
return this.$store.state.userCurCityId;
}
},
watch: {},
methods: {
_initSwiper() {
this.swiper = new Swiper('.swiper-container', {
// speed: 2000,
observer: true, // 当改变swiper的样式(例如隐藏/显示)或者修改swiper的子元素时,自动初始化swiper
observerParents: true, // 将observe应用于Swiper的父元素
freeMode: true, // 惯性滑动
freeModeMomentum: true, // 释放slider后会继续滑动
freeModeMomentumBounceRatio: 0, // 拖动时,至顶部或底部不继续滑动并回滚
resistanceRatio: 0, // 处于顶部或底部时,无法继续向下或向上拖动
direction: 'vertical', // 竖向滑动
slidesPerView: "auto", // 控制单屏显示的slider的数量,设置成auto,是让slider的高度自适应,如果是数字n,则单屏显示n个slider
autoHeight: true, // wrapper和container会随着当前slide的高度而发生变化
setWrapperSize: true,
nested: true
});
},
changeCity(item) {
this.$store.commit('UPDATE_popPanel', 'normal');// 搜索面板恢复默认
this.$store.commit('UPDATE_showCityId', item.id);
this.$store.commit('UPDATE_showCityName', item.name);
if (this.$store.state.userCurLocatedOpen) {
this.jsBrigeUtil.stopUpdataCurLoc(this);
}
this.$router.push({name: 'Home'});
},
handleInput(ev) {
ev = ev || event;
let input = ev.target.value;
this.search(input);
},
// 模糊搜索
search(input) {
let resultList = [];
// let firstWord = input.slice(0, 1).toLowerCase();
for (let i = 0; i < this.allCityList.length; i++) {
/*if (!!Number(firstWord) || !(this.allCityList[i].name.toLowerCase() === firstWord)) {
continue;
}*/
let cityList = this.allCityList[i].data;
for (let j = 0; j < cityList.length; j++) {
if (cityList[j].name.indexOf(input) < 0) {
continue;
}
resultList.push({id: cityList[j].id, name: cityList[j].name});
}
}
this.searchResultList = resultList;
if (this.searchResultList.length > 0) {
this.hasResult = true;
this.hasNoResult = false;
} else {
this.hasResult = false;
this.hasNoResult = true;
}
},
handleSelectCity (item) {
this.changeCity(item);
this.hasResult = false;
this.hasNoResult = false;
},
touchStart(ev) {
ev = ev || event;
if (ev.targetTouches.length > 1) return;
this.startY = ev.targetTouches[0].clientY; // 获取初始点
if (ev.targetTouches[0].target.tagName.toLowerCase() != 'li') return; // 当点击的节点不为li时直接跳出
for (let i = 0; i < this.$refs.cityLetterUl.children.length; i++) {
if (ev.targetTouches[0].target.textContent === this.$refs.cityLetterUl.children[i].innerText) { // 因为无法获取到当前点击的是第几个li,因此通过比较li的textContent和当前点击的li,以找到点击的是第几个li
this.startIndex = i;
break;
}
}
this.letterName = ev.targetTouches[0].target.textContent;
this.swiper.slideTo(this.startIndex, 300, false);
this.letterClick = true;
},
touchMove(ev) {
ev = ev || event;
if (ev.targetTouches.length > 1) return;
this.disY = ev.targetTouches[0].clientY - this.startY; // 计算移动了多少个li,每个li固定了高度为14px
let index = 0;
if (this.disY > 0) {
index = this.startIndex + Math.floor(this.disY / 14);
} else if (this.disY < 0) {
index = this.startIndex + Math.floor(this.disY / 14);
}
if (index >= 0 && index < this.$refs.cityLetterUl.children.length) { // 当在li的数量范围内才显示
this.letterName = this.letterList[index].name;
this.swiper.slideTo(index, 300, false); // 模拟锚点
this.letterClick = true;
}
},
touchEnd(ev) {
ev = ev || event;
if (ev.changedTouches.length > 1) return;
this.letterClick = false;
this.letterName = '';
this.startIndex = 0;
},
handleLetterClick(ev) { // 点击li时执行并模拟锚点
ev = ev || event;
console.log('ev: ', ev);
for (let i = 0; i < this.$refs.cityLetterUl.children.length; i++) {
if (ev.target.text === this.$refs.cityLetterUl.children[i].innerText) {
this.startIndex = i;
break;
}
}
this.letterName = this.$refs.cityLetterUl.children[this.startIndex].innerText;
this.swiper.slideTo(this.startIndex, 300, false);
this.letterClick = true;
setTimeout(() => {
this.letterClick = false;
}, 300);
}
}
}
</script>
<style scoped>
/*搜索块 s*/
.search-div {
width: 94.4vw;
height: 50px;
margin: 10px auto 15px;
border-radius: 5px;
/*line-height: 36px;*/
position: relative;
overflow: hidden;
background-color: #fff;
box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.10);
}
.search-div .search-icon {
display: inline-block;
width: 16px;
height: 16px;
background-image: url("./assets/[email protected]");
background-size: 100% 100%;
position: absolute;
top: 12px;
left: 20px;
}
.search-div input {
width: 86.1vw;
height: 40px;
padding-top: 4px;
box-sizing: border-box;
font-size: 17px;
background: #fff;
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px solid hsla(0, 0%, 60.8%, .5);
display: inherit;
margin: 0 auto;
padding-left: 30px;
/*兼容ios*/
border-radius: 0;
/*解决ios不能输入问题*/
-webkit-user-select: auto;
/* 针对ios设置样式,去除ios下input的椭圆外框*/
-webkit-appearance: none;
}
.search-div input:focus {
outline: none;
}
/*搜索块 e*/
/*常用div s*/
.block-list {
width: 94.4vw;
font-size: 12px;
color: #4A4A4A;
margin: 0 auto 10px;
}
.block-list .grid {
width: 100%;
display: flex;
flex-flow: row wrap;
justify-content: flex-start;
margin-top: 5px;
}
.block-list .grid .grid-cell {
background-color: #fff;
border-radius: 5px;
box-sizing: border-box;
width: 30.5%;
margin: 5px 3.6vw 5px 0;
overflow: hidden;
}
.block-list .grid .grid-cell:active {
background-color: #e1e1e1;
}
.block-list .grid .grid-cell:nth-child(3n) {
margin-right: 0;
}
.block-list .poi-text {
height: 35px;
line-height: 35px;
font-size: 12px;
color: #4A4A4A;
text-align: center;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
padding: 0 10px;
}
.block-list .poi-text .loc-icon {
width: 16px;
height: 16px;
background-image: url("./assets/[email protected]");
background-size: 100% 100%;
vertical-align: text-bottom;
margin-right: 1px;
display: none;
}
.block-list .poi-text .loc-icon.active {
display: inline-block;
}
.city-list-contain-div {
position: relative;
overflow-y: hidden; /* 设置overflow-y为hidden,以避免原生的scroll影响根据手势滑动计算滚动距离 */
background: transparent;
/*解决安卓滑动页面时出现空白*/
-webkit-backface-visibility: hidden;
-webkit-transform: translate3d(0, 0, 0);
height: calc(100% - 60px);
margin-top: 10px;
}
.cur-city-div {
/*margin: 0 auto;*/
}
.block-list .cur-city-text {
color: #2A70FE;
}
/* */
.pop-use-div {
}
/* 站点列表和搜索结果列表 */
.all-city-div, .search-result-div {
width: 100%;
color: #4a4a4a;
margin: 0 auto;
}
.search-result-div {
height: calc(100% - 75px);
}
.search-result-div ul {
height: 100%;
overflow-y: auto;
}
.all-city-div .city-list-anchor {
width: 94.4vw;
margin: 0 auto;
}
.all-city-div ul, .search-result-div ul {
width: 100%;
list-style: none;
display: block;
position: relative;
background-color: #fff;
}
.all-city-div ul li, .search-result-div ul li {
font-size: 15px;
line-height: 40px;
height: 40px;
width: 94.4vw;
margin: 0 auto;
border-bottom: 1px solid rgba(155, 155, 155, .5);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
/* 没有搜索结果 */
.no-result {
box-sizing: border-box;
padding: 10px;
color: #4A4A4A;
width: 100%;
text-align: center;
font-size: 12px;
}
/* 锚点 */
.city-letter-div {
z-index: 1;
position: absolute;
overflow: hidden;
padding-right: 2.9vw;
top: 50%;
right: 0;
transform: translateY(-50%);
font-size: 10px;
text-align: center;
}
.city-letter-div ul li {
line-height: 14px;
color: #2A70FE;
}
.city-letter-select {
z-index: 1;
width: 50px;
height: 50px;
background-color: #fff;
color: #4A4A4A;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% -50%);
text-align: center;
line-height: 50px;
}
</style>
问题:在使用swiper的时候会遇到一个问题,因为效果是,滑到最底时便不能再向上滑动了,但是无论怎么滑动,都无法滑动到最底部,就无法看到最底部的数据。
呼呼呼~终于知道上面那个问题是为啥了,原来我给滑动的内容设置了相对父级高度100%了,忘记减掉了输入框所占的高度了。所以给滑动框内容高度减掉输入框所占据的高度就好了。