Small program realizes the pits encountered in the index bar

Recently, when I was working on a small program project, I encountered something with the function of the index bar. This project is a requirement for selecting a car model. First look at the renderings: the
Insert picture description here
Insert picture description here
Insert picture description here
realization of the above functions may include customizing the pop-up box, clicking the index letter to jump to the corresponding position, and searching the keyword highlighting. Let's implement them one by one below.

Special note : When I first saw this kind of index bar component, I thought of using vant's indexBar component, but when the popup component indexBar is used later, clicking on the index letter is invalid, because the pop-up layer of the popup needs to be positioned and jumped The position of the corresponding letter is invalid, it is a pit! !

css code

<!-- 蒙层 -->
        <view class="remark" wx:if="{
    
    {showBrand}}" bindtap="closeBrand" catchtouchmove="preventTouchMove"></view>
        <!-- 内容 -->
        <view class="re-con" wx:if="{
    
    {showBrand}}">
          <view class="cityBox" wx:if="carBrandList">
            <view class="search-city">
              <view class="search-con">
                <icon class="iconfont icon-fangdajing" bindtap="searchKey"></icon>
                <input placeholder="请输入车型搜索" type="text" value="{
    
    {searchValue}}" bindinput="getCity"/>
              </view>
            </view>
            <view class="content">
              <view class="all-city">
                <scroll-view class="city-scroll {
    
    {isFirstId?'':'city-scoll-height'}}" scroll-y="true" scroll-with-animation="true" scroll-into-view="{
    
    {toView}}">
                  <view class="city-list" wx:if="{
    
    {!searchList.length}}">
                    <!-- 循环城市列表 start -->
                    <view wx:for="{
    
    {carBrandList}}" wx:key="index" id="{
    
    {'city'+index}}" catchtap='selectcity' data-initial="{
    
    {item.initial}}" class="listGroup">
                      <!-- 字母导航 -->
                      <view class="nav-text">
                        <text class="{
    
    {index==currentInitial?'currentClass':''}}">{
    
    {
    
    item.initial}}</text>
                      </view>
                      <!-- 汽车一级品牌名字 -->
                      <view class="show-city">
                        <radio-group class="radio-group" bindchange="radioChange" wx:if="{
    
    {!isFirstId}}">
                          <view class="city-item" wx:for="{
    
    {item.carBrandInfoList}}" wx:key="index" data-name="{
    
    {item.name}}" data-vendorid="{
    
    {item.parentId}}" data-obj="{
    
    {item}}" bindtap="clickFirstId">
                            <label for="{
    
    {item.carModelId}}">
                              <image src="{
    
    {item.logo}}"></image>
                              <text class="text">{
    
    {
    
    item.name}}</text>
                            </label>
                            <radio class="radio" id="{
    
    {item.carModelId}}" hidden="{
    
    {car.carModelId!=item.recordId}}" value="{
    
    {item.name}}" checked="{
    
    {car.carModelId==item.recordId}}" color="#28b8ff"></radio>
                          </view>
                        </radio-group>
                        <block wx:else>
                          <view class="city-item" wx:for="{
    
    {item.carBrandInfoList}}" wx:key="index" data-name="{
    
    {item.name}}" data-obj="{
    
    {item}}" bindtap="clickFirstId">
                            <image src="{
    
    {item.logo}}"></image>
                            <text>{
    
    {
    
    item.name}}</text>
                          </view>
                        </block>
                      </view>
                    </view>
                    <!-- 循环城市列表 end -->
                  </view>
                  <!-- 关键词搜索的列表 -->
                  <view class="city-list" wx:if="{
    
    {searchList.length}}">
                    <view wx:for="{
    
    {searchList}}" wx:key="index" id="{
    
    {'city'+index}}" catchtap='selectcity' data-initial="{
    
    {item.initial}}">
                      <view class="show-city">
                        <radio-group class="radio-group" bindchange="radioChange">
                          <view class="city-item" data-name="{
    
    {item.fullName}}" data-vendorid="{
    
    {item.vendorId}}" data-obj="{
    
    {item}}" bindtap="clickFirstId">
                            <label for="{
    
    {item.recordId}}">
                              <!-- <text >{
    
    {
    
    item.fullName}}</text> -->
                              <text wx:for="{
    
    {item.fullName}}" wx:key="index" class="{
    
    {item ==  searchValue? 'currentClass' : '' }}">{
    
    {
    
    item}}</text>
                            </label>
                            <radio class="radio" id="{
    
    {item.recordId}}" hidden="{
    
    {car.carModelId!=item.recordId}}" value="{
    
    {item.fullName}}" checked="{
    
    {car.carModelId==item.recordId}}" color="#28b8ff"></radio>
                          </view>
                        </radio-group>
                      </view>
                    </view>
                  </view>
                </scroll-view>
              </view>
              <!-- 字母索引 start -->
              <view class="search-nav" wx:if="{
    
    {isFirstId&&!searchList.length}}">
                <text bindtap="cityScroll" data-initial="{
    
    {item.initial}}" data-index="{
    
    {index}}" wx:for="{
    
    {carBrandList}}" wx:key="index" class="navlist {
    
    {index==currentInitial?'currentClass':''}}" catchtouchmove="preventTouchMove">{
    
    {
    
    item.nav}}</text>
              </view>
              <!-- 字母索引 end -->
            </view>
          </view>
          <!-- 取消确定 -->
          <view class="foot-btn" wx:if="{
    
    {!isFirstId}}">
            <view>
              <view class="cancel" bindtap="clickReset">重置</view>
              <view class="comfir" bindtap="clickComfir">确认</view>
            </view>
          </view>
        </view>

js code

1. Click the index letter on the right to jump to the corresponding position

// 点击英文字母进行跳转到相应位置
  cityScroll(e) {
    
    
    let data = this.data.carBrandList
    let Index = e.currentTarget.dataset.index
    let initial = data[Index].initial
    console.log(initial)
    if (data.length) {
    
    
      data.map((res, index) => {
    
    
        if (initial == res.initial) {
    
    
          this.setData({
    
    
            currentInitial: index,
            toView: `city${
    
    index}`//用于定位
          })
        }
      })
    }
    wx.showToast({
    
    
      title: initial,
      icon: 'none'
    })
  },

The toView above uses the scroll-into-view property of the scroll-view component of the applet (the value should be a child element id (id cannot start with a number). Set which direction to scroll, then scroll to the element in which direction) Set an id for the top-level element of each car model (the first letter is A), corresponding to the id="{ {'city'+index}}" bound above , you can get the current index when you click it, and then Realize the jump.

2. Search keywords highlight

//搜索关键词
  searchKey() {
    
    
    this.setData({
    
    
      isFirstId: false
    })
    if (this.data.searchValue) {
    
    
      netRequest.webRequest(getApi.getKeyWords, {
    
    
        keyWords: this.data.searchValue
      }, "get").then(res => {
    
    
        let data = res.data
        if (data.length) {
    
    
          data.map(item => {
    
    
            item.fullName = this.getSpit(item.fullName, item.brandName)
          })
          this.setData({
    
    
            searchList: data
          })
          this.searchTap()
        }
      })
    } else {
    
    
      this.setData({
    
    
        searchList: '',
        carBrandList: this.data.copyBrand,
        isFirstId: true
      })
    }
  },
  //处理关键词高亮
  searchTap: function() {
    
    
    var that = this;
    that.setData({
    
    
      listDataCopy: that.data.searchList//搜索关键词后台返回的搜索列表
    })
    var data = that.data.searchList;
    var newData = that.data.listDataCopy;
    for (var i = 0; i < data.length; i++) {
    
    
      var dic = data[i]
      var newDic = newData[i]
      var fullName = dic["fullName"]
      newDic["fullName"] = this.getInf(fullName, that.data.searchValue);
    }
    that.setData({
    
    
      searchList: newData,
    })
    console.log(this.data.searchList)
  },
   //整理关键词
  getInf(str, key) {
    
    
    return str.toString().replace(new RegExp(`${
    
    key}`, 'g'), `%%${
    
    key}%%`).split('%%')
  },

Implementation idea: First, get the list of search values ​​returned in the background according to the keywords, and then traverse the array to get the attributes that need to be displayed. The example is fullName. Pass the search keywords and the traversed fullName into the getInf function, which is implemented in fullName (There must be a keyword string in the fullName, because it is the value searched for based on the keyword). After finding the fullName, separate the fullName, such as fluuName="BMW X5M" and the keyword is "BMW", then getInf returns ["","BMW","X5M"] array, then traverse this array in the interface, and if the traversed item is the same as the search value "BMW", then add the highlighted calss, the above example is the second of the array ( The subscript is 1) highlight calss will be added to achieve the highlight effect of the keyword "BMW".

extensions


To achieve this function , the index letter list on the right side of the finger slides to jump to the corresponding position . Because of the scroll-view component, there is an animation delay in this project to achieve this function. You can refer to the following ideas: if
you want to slide your finger to the index to jump to the corresponding position, you need to calculate the height of each piece, and obtain the calculated difference between the touched pageY and the constantly changing pageY/height of each index element, the code as follows:

 //获取每一项组合的高度(根据首字母分组)
  calculateHeight() {
    
    
    let that = this
    const query = wx.createSelectorQuery()
    const list = query.selectAll('.listGroup')
    if (this.data.isFirstId) {
    
    
      const height = query.select('.navlist')
      //获取第一个字母索引元素的高度
      height.boundingClientRect(function(rect) {
    
    
        that.setData({
    
    
          height: rect.height
        })
      }).exec()
    }
    let arr = []
    list.boundingClientRect(function(rect) {
    
    
      if (rect.length) {
    
    
        rect.map(res => {
    
    
          arr.push(res.height)
        })
        that.setData({
    
    
          listHeight: arr
        })
        console.log(arr)
      }
    }).exec()
  },

The wx.createSelectorQuery in the above figure is the api that the applet comes with to get the demo element. Portal => boundingClientRect
This api can directly get the height, width, left, right, top, bottom and other information of the element.

Conclusion

The stroke is over. It’s a bit rush to write in my free time, please contact me if you make any mistakes! My WeChat: huang009516

Guess you like

Origin blog.csdn.net/Smell_rookie/article/details/103772538