小程序 通讯录

实例效果

实现功能

1.上下滑动通讯录,右侧导航栏与顶部跟随响应

2.点击右侧导航栏,通讯录跳转到响应位置

思路

1、通讯录内容用scroll-view包住,利用scroll-view提供的bindscroll方法,此方法在滚动时触发(要给scroll-view添加一个默认高度,这个默认高度一般是手机屏幕默认高度,否则可能无法触发方法,因为scroll-view此时视为没有滚动)。方法触发时,能够通过参数获取屏幕实时高度,创建一个数组存储每一组(A、B、C...)的屏幕高度,通过比较控制右侧列表响应。顶部导航栏的实现思路与此基本相同。

2、利用scroll-view提供的scroll-into-view属性,在点击右侧导航栏时,通过变量控制使得通讯录跳转到相应位置

 

整体实现起来有相当多的细节,例如怎么设置存储屏幕高度的数组,窗体高度如何获取,怎么利用scroll-into-view属性

 

wxml

<view class="page">
  <scroll-view scroll-y="true" bindscroll="scroll" style="height: {{ windowHeight?windowHeight+'px':'' }}" scroll-into-view="{{ toView }}" scroll-with-animation="true">
    <view wx:for="{{ addressList }}" wx:for-item="item" wx:for-index="indexType" wx:key="indexType">
      <view class="item" id="{{ 'list'+indexType }}">
        <view class="type">{{ item.type }}</view>
        <block wx:for="{{ item.members }}" wx:for-item="member" wx:for-index="index" wx:key="index">
          <view class="member {{ index>0?'border-top-line':'' }}">
            <image src="{{ member.img }}" class="img"></image>
            <text class="name">{{ member.name }}</text>
          </view>
        </block>
      </view>
    </view>
  </scroll-view>

  <!-- 右侧列表 -->
  <view class="list">
    <block wx:for="{{ list }}" wx:for-item="item" wx:for-index="index" wx:key="index">
      <view class="{{ currentList==index?'current-list':'' }}" bindtap="addressListAnswer" data-index="{{ index }}">
        {{ item }}
      </view>
    </block>
  </view>

  <!-- 顶部列表 -->
  <view class="topbar">
    {{ list[currentList] }}
  </view>

</view>

wxss

/* pages/addressList/addressList.wxss */

.page {
  width: 90%;
  margin: 0 auto;
}

.item {
  margin: 40rpx 0;
}

.type {
  color: #999999;
  font-size: 26rpx;
}

.member {
  display: flex;
  align-items: center;
  padding: 15rpx 0;
}

.img {
  width: 80rpx;
  height: 80rpx;
  border-radius: 40rpx;
}

.name {
  margin-left: 20rpx;
}

.border-top-line {
  border-top: 1px solid #eeeeee;
}

.list {
  position: fixed;
  top: 40rpx;
  right: 14rpx;
  font-size: 26rpx;
  color: #999999;
}

.current-list {
  color: #ff8866;
}

.topbar {
  position: fixed;
  top: 0;
  width: 88%;
  color: white;
  background-color: #ff8866;
  text-align: center;
  font-size: 26rpx;
}

js

// pages/addressList/addressList.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    // 列表数据层
    addressList: [{
        type: 'A',
        members: [{
            img: '/images/1.jpg',
            name: 'Amy',
          },
          {
            img: '/images/2.jpg',
            name: 'Amy',
          },
          {
            img: '/images/3.jpg',
            name: 'Amy',
          },
        ]
      },
      {
        type: 'B',
        members: [{
            img: '/images/1.jpg',
            name: 'Bili',
          },
          {
            img: '/images/2.jpg',
            name: 'Bili',
          },
          {
            img: '/images/3.jpg',
            name: 'Bili',
          },
          {
            img: '/images/4.jpg',
            name: 'Bili',
          },
          {
            img: '/images/5.jpg',
            name: 'Bili',
          }
        ]
      },
      {
        type: 'C',
        members: [{
            img: '/images/1.jpg',
            name: 'Cat',
          },
          {
            img: '/images/2.jpg',
            name: 'Cat',
          },
          {
            img: '/images/3.jpg',
            name: 'Cat',
          },
          {
            img: '/images/4.jpg',
            name: 'Cat',
          },
          {
            img: '/images/5.jpg',
            name: 'Cat',
          }
        ]
      },
      {
        type: 'D',
        members: [{
            img: '/images/1.jpg',
            name: 'Dave',
          },
          {
            img: '/images/2.jpg',
            name: 'Dave',
          },
          {
            img: '/images/3.jpg',
            name: 'Dave',
          },
          {
            img: '/images/4.jpg',
            name: 'Dave',
          },
          {
            img: '/images/5.jpg',
            name: 'Dave',
          }
        ]
      },
      {
        type: 'O',
        members: [{
            img: '/images/1.jpg',
            name: 'Olive',
          },
          {
            img: '/images/2.jpg',
            name: 'Olive',
          },
          {
            img: '/images/3.jpg',
            name: 'Olive',
          },
          {
            img: '/images/4.jpg',
            name: 'Olive',
          },
          {
            img: '/images/5.jpg',
            name: 'Olive',
          }
        ]
      },
      {
        type: 'P',
        members: [{
            img: '/images/1.jpg',
            name: 'Panda',
          },
          {
            img: '/images/2.jpg',
            name: 'Panda',
          },
          {
            img: '/images/3.jpg',
            name: 'Panda',
          },
          {
            img: '/images/4.jpg',
            name: 'Panda',
          },
          {
            img: '/images/5.jpg',
            name: 'Panda',
          }
        ]
      },
      {
        type: 'R',
        members: [{
            img: '/images/1.jpg',
            name: 'Rabbit',
          },
          {
            img: '/images/2.jpg',
            name: 'Rabbit',
          },
          {
            img: '/images/3.jpg',
            name: 'Rabbit',
          },
          {
            img: '/images/4.jpg',
            name: 'Rabbit',
          },
          {
            img: '/images/5.jpg',
            name: 'Rabbit',
          }
        ]
      },
      {
        type: 'T',
        members: [{
            img: '/images/1.jpg',
            name: 'Tom',
          },
          {
            img: '/images/2.jpg',
            name: 'Tom',
          },
          {
            img: '/images/3.jpg',
            name: 'Tom',
          },
          {
            img: '/images/4.jpg',
            name: 'Tom',
          },
          {
            img: '/images/5.jpg',
            name: 'Tom',
          }
        ]
      },
    ],

    // 每个类型在页面中的高度
    addressListHeight: [],

    // 右侧列表内容
    list: [],

    // 窗体默认高度
    windowHeight: 0,

    // 右侧列表响应控制
    currentList: 0,

    // 控制变量:点击右侧列表通讯录响应
    toView: '',
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    wx.setNavigationBarTitle({
      title: '通讯录',
    });

    // 获取窗体高度
    wx.getSystemInfo({
      success: (result) => {
        this.setData({
          windowHeight: result.windowHeight
        })
      },
    })

    this.getRightList();
    this.getTypeHeight();
  },

  // 获取类型高度
  getTypeHeight: function (e) {
    let typeHeight = [];
    wx.createSelectorQuery().selectAll('.type').boundingClientRect((rects) => {
      rects.forEach((item, index) => {
        typeHeight.push(item.top);
      })
    }).exec();
    this.setData({
      addressListHeight: typeHeight
    });
  },

  // 根据通讯录数据动态生成右侧列表
  getRightList: function (e) {
    let list = [];
    this.data.addressList.forEach((item, index) => {
      list.push(item.type);
    });
    this.setData({
      list: list
    });
  },

  // 通讯录滚动时触发,右侧列表响应
  scroll: function (e) {
    this.answer(e.detail.scrollTop);
  },

  // 右侧列表响应方法
  answer: function (currentHeight) {
    let addressListHeight = this.data.addressListHeight;
    for(let i = 1, len = addressListHeight.length; i < len; i++) {
      if (currentHeight >= addressListHeight[i-1] && currentHeight < addressListHeight[i]) {
        this.setData({
          currentList: i-1
        });
        break;
      }
    }
  }, 

  // 点击右侧列表,通讯录响应方法
  addressListAnswer: function (event) {
    console.log(event);
    let index = event.currentTarget.dataset.index;
    this.setData({
      toView: 'list'+index
    })
  }
  

})

再附上一个GitHub链接吧:通讯录

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值