iview 框架 index 组件在ios 中由于层级关系字母索引被挡住问题
框架代码修改
<view class="i-index i-class">
<scroll-view
scroll-y
style="overflow: visible;"
style="{{parse.setScrollStyle(height)}}"
bindscroll="handlerScroll"
scroll-top="{{scrollTop}}">
<slot></slot>
<view class="i-index-tooltip" style="{{ isTouches ? 'display:block' : 'display:none' }}">{{currentName}}</view>
</scroll-view>
<view class="i-index-fixed"
catchtouchstart="handlerTouchMove"
catchtouchmove="handlerTouchMove"
catchtouchend="handlerTouchEnd">
<view class="i-index-fixed-item"
wx:for="{{fixedData}}"
wx:key="{{index}}"
data-index="{{index}}"
catchtap="handlerFixedTap">
{{item}}
</view>
</view>
</view>
<wxs module="parse">
module.exports = {
setScrollStyle : function(height){
var units = ['%','px','rem','rpx','em','rem'];
var hasUnits = false;
for( var i = 0; i < units.length;i++ ){
var u = units[i];
if( height.indexOf( u ) > -1 ){
hasUnits = true;
break;
}
}
return 'height:'+ ( hasUnits ? height : height+'px' )+';overflow: visible';
}
}
</wxs>
Component({
externalClasses: ['i-class'],
properties : {
height : {
type : String,
value : '300'
},
itemHeight : {
type : Number,
value : 18
},
scrollTop:{
type : Number,
value : 0
}
},
relations : {
'../index-item/index' : {
type : 'child',
linked(){
this.setData({
fixedData : []
})
this._updateDataChange();
},
linkChanged () {
this._updateDataChange();
},
unlinked () {
this.setData({
fixedData : []
})
this._updateDataChange();
}
}
},
data : {
scrollTop : 0,
fixedData : [],
current : 0,
timer : null,
startTop : 0,
itemLength : 0,
currentName : '',
isTouches : false
},
methods : {
loop(){},
_updateDataChange( ){
const indexItems = this.getRelationNodes('../index-item/index');
const len = indexItems.length;
const fixedData = this.data.fixedData;
/*
* 使用函数节流限制重复去设置数组内容进而限制多次重复渲染
* 暂时没有研究微信在渲染的时候是否会进行函数节流
*/
if (len > 0) {
if( this.data.timer ){
clearTimeout( this.data.timer )
this.setData({
timer : null
})
}
this.data.timer = setTimeout(()=>{
const data = [];
indexItems.forEach((item) => {
if( item.data.name && fixedData.indexOf( item.data.name ) === -1 ){
data.push(item.data.name);
item.updateDataChange();
}
})
this.setData({
scrollTop:0,
fixedData : data,
itemLength : indexItems.length
})
//组件加载完成之后重新设置顶部高度
this.setTouchStartVal();
},0);
this.setData({
timer : this.data.timer
})
}
},
handlerScroll(event){
const detail = event.detail;
const scrollTop = detail.scrollTop;
const indexItems = this.getRelationNodes('../index-item/index');
indexItems.forEach((item,index)=>{
let data = item.data;
let offset = data.top + data.height;
if( scrollTop < offset && scrollTop >= data.top ){
this.setData({
current : index,
currentName : data.currentName
})
}
})
},
getCurrentItem(index){
const indexItems = this.getRelationNodes('../index-item/index');
let result = {};
if(indexItems[index-1]){
result = indexItems[index-1].data;
result.total = indexItems.length;
return result;
}
},
triggerCallback(options){
this.triggerEvent('change',options)
},
handlerFixedTap(event){
const eindex = event.currentTarget.dataset.index;
const item = this.getCurrentItem(eindex);
this.setData({
scrollTop : item.top - data.scrollTop,
currentName : item.currentName,
isTouches : true
})
this.triggerCallback({
index : eindex,
current : item.currentName
})
},
handlerTouchMove(event){
const data = this.data;
const touches = event.touches[0] || {};
const pageY = touches.pageY;
const rest = pageY - data.startTop;
let index = Math.ceil( rest/data.itemHeight );
index = index >= data.itemLength ? data.itemLength -1 : index;
const movePosition = this.getCurrentItem(index);
/*
* 当touch选中的元素和当前currentName不相等的时候才震动一下
* 微信震动事件
*/
if(!movePosition){
return false;
}
if( movePosition.name !== this.data.currentName ){
wx.vibrateShort();
}
this.setData({
scrollTop : movePosition.top,
currentName : movePosition.name,
isTouches : true
})
this.triggerCallback({
index : index,
current : movePosition.name
})
},
handlerTouchEnd(){
this.setData({
isTouches : false
})
},
setTouchStartVal(){
const className = '.i-index-fixed';
const query = wx.createSelectorQuery().in(this);
query.select( className ).boundingClientRect((res)=>{
console.log(res)
if(res&&res.top){
this.setData({
startTop : res?res.top:0
})
}
}).exec()
}
}
})
页面代码
<template>
<div class="container">
<div class="containerTop">
<div class="search">
<div :class="isInput?'search-left col-8':'search-left'">
<i-icon type="search" i-class="icon-b" size="24" />
<i-input i-class="input-b"
@focus="focus"
maxlength="10000"
:value="value"
type="text"
@change="getChange"
placeholder="搜索目的地" />
</div>
<div v-show="isInput" class="search-right" @click="isInput=false">取消</div>
</div>
<div class="tabs">
<i-tabs :current="current" @change="tabsSelect" color="#19be6b">
<i-tab key="1" title="国内" i-class="tab"></i-tab>
<i-tab key="2" title="海外" i-class="tab"></i-tab>
</i-tabs>
</div>
<!--热门城市-->
<div class="hot" v-show="!isInput">
<div class="title">热门城市</div>
<i-row>
<i-col span="8" v-for="(item,index) in hotList" v-if="index<12" :key="index">
<div class="x-btn" @click="setSite(item,'nameChn')">{{item.nameChn}}</div>
</i-col>
</i-row>
</div>
<!--索引index组件-->
<div class="view" v-show="!isInput">
<i-index height="100%" v-if="siteList&¤t==1" :scrollTop="scrollTop">
<i-index-item
v-for="(item,index) in siteList" :key="index"
:name="item.key">
<div class="i-index-demo-item" @click="setSite(item1,'name')" v-for="(item1,inx) in item.list" :key="inx">
{{item1.name}}
</div>
</i-index-item>
</i-index>
<i-index height="100%" v-if="siteList&¤t==2" :scrollTop="scrollTop">
<i-index-item
v-for="(item,index) in siteList" :key="index"
:name="item.key">
<div class="i-index-demo-item" @click="setSite(item1,'name')" v-for="(item1,inx) in item.list" :key="inx">
{{item1.name}}
</div>
</i-index-item>
</i-index>
</div>
</div>
<!--搜索列表-->
<div class="search-list" v-show="isInput">
<i-cell-group v-for="(item,index) in searchList" :key="index">
<i-cell
is-link
:title="item.nameChn"
i-class="bor-b"
@click="setSite(item,'nameChn')">
</i-cell>
</i-cell-group>
</div>
</div>
</template>
<script>
import { mapActions, mapState} from "vuex";
export default{
components:{
},
async onShow(){
if(this.site.nation=="中国"){
this.init(this.siteInlandList);
this.current = 1;
}else{
this.init(this.siteForeignList);
this.current = 2;
}
},
computed:{
...mapState({
siteInlandList:state=>state.siteList,
siteForeignList:state=>state.siteForeignList,
site:state=>state.site
})
},
data(){
return {
current:1,
scrollTop:0,//index索引距离顶部距离高度
value:"",
siteList:null,
isInput:false,//是否获取到焦点
hotList:[],
searchList:[]
}
},
methods:{
//选项卡切换
tabsSelect(obj){
this.current = obj.mp.detail.key ;
if(this.current==1){
this.init(this.siteInlandList);
}else{
this.init(this.siteForeignList);
}
},
focus(){
this.isInput = true;
this.search();
},
getChange(value){
this.value = value.mp.detail.detail.value;
this.search();
},
//点击搜索列表
setSite(item,filed){
var data = {
city:item[filed],
...item,
showCon:true
};
if(this.current==1){
data.nation = "中国";
}else{
data.nation = "海外";
}
this.isInput = false ;
this.$store.commit("SET_SITE",data);
wx.navigateBack();
},
//搜索列表
search(){
this.searchList = this.hotList.filter((e)=>{
return e.nameChn.indexOf(this.value)>-1||this.value.indexOf(e.nameChn)>-1;
})
},
init(data){
this.siteList = null;
this.searchList = [];
this.value = this.$store.state.site.city;
this.hotList = data;
this.searchList = data;
//设置
var cities = data;
//const words = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
let wordsList = [];
cities.forEach((item)=>{
wordsList.push(item.nameEng.substring(0,1));
})
var words = wordsList.filter((e,i,slef)=>{
return slef.indexOf(e)==i
})
words = words.sort(function compareFunction(param1, param2) {
return param1.localeCompare(param2,"zh");
}
)
let storeCity = new Array(words.length);
words.forEach((item,index)=>{
storeCity[index] = {
key : item,
list : []
}
})
cities.forEach((item)=>{
let firstName = item.nameEng.substring(0,1);
let index = words.indexOf(firstName);
storeCity[index].list.push({
name : item.nameChn,
key : firstName,
cityId:item.cityId,
countryId:item.countryId,
nameEng:item.nameEng,
});
})
this.siteList = [];
this.siteList = storeCity;
}
},
onLoad(){
var than = this ;
wx.getSystemInfo({
success:function(res){
than.scrollTop = parseInt((res.screenWidth/750)*680);
}
})
}
}
</script>
<style lang="css">
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
}
view{
overflow: visible;
}
.tab{
padding: 0 20rpx;
}
/*搜索*/
.search{
width: 674rpx;
margin: 0 auto;
height: 70rpx;
overflow: hidden;
}
.search-left{
overflow: hidden;
border-radius: 14rpx;
width: 100%;
background: #f8faf9;
padding-left: 16rpx;
float: left;
position: relative;
}
.containerTop{
height: 680rpx;
}
.col-8{
width: 80%;
}
.search-left .icon-b{
color: #07c687;
display: inline-block;
vertical-align: middle;
}
.search-left .input-b{
padding: 0;
padding: 0;
display:inline-block;
vertical-align: middle;
background: none;
width: 80%;
}
.search-right{
float: left;
font-size: 28rpx;
color: #ccc;
line-height: 70rpx;
padding-left: 20rpx;
}
/*下划线*/
.bor-b{
border-bottom:2rpx solid #ccc ;
}
.search-list{
width: 674rpx;
margin: 0 auto;
position: absolute;
left: 38rpx;
top: 70rpx;
bottom: 0;
overflow: auto;
}
.hot{
width: 674rpx;
margin: 0 auto;
position: relative;
z-index: 1;
}
.hot .title{
font-size: 30rpx;
color: #222;
line-height: 30rpx;
padding-top: 30rpx;
margin-bottom: 10rpx;
}
.hot .x-btn{
height: 60rpx;
line-height: 60rpx;
margin: 12rpx 20rpx;
text-align: center;
background: #fafafa;
border: 2rpx solid #ddd;
font-size: 28rpx;
color: #222;
}
/*索引*/
.view{
width: 100%;
position: absolute;
top:680rpx;
bottom: 0;
z-index: 1000;
}
.i-index-demo-item{
padding: 20rpx;
border-bottom: 2rpx solid #ccc;
}
</style>