首页 > 编程语言 >小程序之index索引器品牌篇实现与步骤详述

小程序之index索引器品牌篇实现与步骤详述

时间:2024-01-14 20:12:04浏览次数:21  
标签:详述 index img brand 索引 brandName static png

小程序之index索引器品牌篇实现与步骤详述

图例

index组件

.js

// 品牌索引列表
Component({
    /** 组件的属性列表 */
    properties: {
        /** 数据 */
        data: {
            type: Object,
            value: {},
            observer: function(newVal, oldVal) { this.resetRight(newVal); }
        },
        /**  配置项 */
        config: {
            type: Object,
            value: {
                animation: true, // 过渡动画是否开启
                search: true, // 是否开启搜索
                searchHeight: 45, // 搜索条高度
                suctionTop: true // 是否开启标题吸顶
            }
        }
    },

    data: {
        list: [],
        rightArr: [], // 右侧字母展示
        jumpNum: '', //跳转到那个字母
        topGroup: [], // 内容高度数据
        pos: {
            isTop: false,
            y: 0,
            oldIndex: -1
        },
        listIndex: 0,
        moveDistance: 0
    },
    ready() {},
    methods: {
        /** 数据重新渲染 */
        resetRight(data) {
            let rightArr = [];
            for (let i in data) { rightArr.push(data[i].key); }

            this.setData({
                list: data,
                rightArr
            }, () => {
                if (data.length != 0) {
                    this.queryMultipleNodes();
                }
            });
        },
        /** 右侧字母点击事件  */
        jumpMt(e) {
            let jumpNum = e.currentTarget.dataset.id;
            this.setData({ jumpNum });
        },
        /** 列表点击事件 */
        detailMt(e) {
            let detail = e.currentTarget.dataset.detail;
            let data = {type: "CLICK", data: detail};
            this.triggerEvent('brand', data);
        },
        // 获取搜索输入内容
        input(e) {
            this.value = e.detail.value;
        },
        // 基础搜索功能
        searchMt() {
            let data = {type: "SEARCH", data: this.value ? this.value : ""};
            this.triggerEvent('brand', data);
        },
        /**  监听滚动 */
        scroll(e) {
            let top = e.detail.scrollTop;
            let index = this.currentIndex(top);
            let list = this.data.topGroup;
            let distance = top - list[this.data.listIndex];
            let num = -(list[this.data.listIndex + 1] - top - 40);
            // 渲染滚动索引
            if (index !== this.data.listIndex) {
                this.setData({
                    listIndex: index,
                    moveDistance: 40,
                })
                // 如果监听到 index 的变化 ,一定要return ,否则吸顶会先变化文字后运动,会闪烁
                return;
            }
            if (num < 0) num = 0;
            if (num !== this.data.moveDistance) { this.setData({ moveDistance: num }) }
        },
        /**
         * 获取当前滚动索引
         */
        currentIndex(y) {
            let listHeight = this.data.topGroup;
            for (let i = 0; i < listHeight.length; i++) {
                let height1 = listHeight[i];
                let height2 = listHeight[i + 1];
                if (!height2 || (y >= height1 && y < height2)) {
                    return i;
                }
            }
            return 0;
        },
        /**
         * 获取节点信息
         */
        queryMultipleNodes() {
          let self = this 
            const query = wx.createSelectorQuery().in(this);
            query.selectAll('.fixed-title-hock').boundingClientRect((res) => {
                res.forEach(function(rect) { rect.top // 节点的上边界坐标 })
            }).exec((e) => {
                let arr = [];
                e[0].forEach((rect) => {
                    let num = 0;
                    if (rect.top !== 0) {
                      num = rect.top - (self.data.config.search ? self.data.config.searchHeight : 0);
                    }
                    arr.push(num);
                })
                this.setData({ topGroup: arr });
            })
        }

    }
})

.json

{
    "component": true,
    "usingComponents": {}
}

.wxml

<view class='list-warpper'>
    <!-- 搜索框 -->
    <view wx:if="{{config.search}}" class='list-search' style="height:{{config.searchHeight}}px">
        <view class='list-search-box'>
            <icon type="search" size="15" />
            <input placeholder="输入品牌名称" bindinput='input' />
        </view>
        <button class='search-button' catchtap='searchMt'>搜索</button>
    </view>
    <view wx:if="{{config.suctionTop}}" class='fiexed-box list-title' style='transform: translateY(-{{moveDistance}}px);top:{{config.search?90:0}}rpx'>
        {{list[listIndex].key  === "HOT" ? "热门品牌" : list[listIndex].key}}
    </view>

    <!-- 搜索到所有数据的时候显示 -->
    <block wx:if="{{list.length != 0 }}">
        <scroll-view class="list-scroll {{config.search?'top':''}}" 
        style=" padding-top:{{config.search?config.searchHeight:0}}px" 
        scroll-y="true" scroll-into-view="{{jumpNum}}" 
        scroll-with-animation="{{config.animation}}" 
        bindscroll="scroll">
            <!-- 主体内容显示 -->
            <view id="{{'index'+index}}" wx:for="{{list}}" wx:key="key">
                <view class='list-title fixed-title-hock'>{{item.key === "HOT" ? "热门品牌" : item.key}}</view>
                <block wx:if="{{ item.key === 'HOT' }}">
                    <view class="index-brand-box">
                        <view wx:for="{{item.list}}" 
                        wx:for-index="in" 
                        wx:key="in" 
                        wx:for-item="it"
                        class="index-brand-card"
                        data-detail="{{it}}"
                        catchtap="detailMt">
                            <view class="brand-img"><image src="{{it.img}}" class="brand-pic"></image></view>
                            <view class="brand-name"> {{it.brandName}} </view>
                        </view>
                    </view>
                </block>
                <block wx:else>
                    <view                           
                        class="index-brand-item" 
                        wx:for="{{item.list}}" 
                        wx:for-index="in" 
                        wx:key="in" 
                        wx:for-item="it"
                        data-detail="{{it}}"
                        catchtap="detailMt">
                        <view class="dflex-start">
                            <view class="brand-img"><image src="{{it.img}}" class="brand-pic"></image></view>
                            <view> {{it.brandName}} </view>
                        </view>
                    </view>
                </block>
            </view>
        </scroll-view>

        <!-- 右侧索引显示 -->
        <view class='list-right-wrapper'>
            <block wx:for="{{rightArr}}" wx:key="rightArr">
                <view wx:if="{{rightArr[index] === 'HOT'}}" class='right-item {{listIndex == index?"active":""}} icon48' data-id="{{'index'+index}}" catchtap='jumpMt'>♡</view>
                <view wx:else class='right-item {{listIndex == index?"active":""}}' data-id="{{'index'+index}}" catchtap='jumpMt'>
                    {{rightArr[index]}}
                </view>          
            </block>
        </view>
    </block>

    <!-- 没有搜索到数据的时候显示 -->
    <block wx:else>
        <view class='nodata'>没有搜索到相关的数据哦</view>
    </block>
</view>

.wxss

.list-warpper {
  position: relative;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}

.list-scroll {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}
.list-scroll.top{
  padding-top: 90rpx;
}

/* 样式控制  */
.list-title {
  background: #f5f5f5;
  color: #666;
  font-size: 36rpx;
  padding-left: 30rpx;
  height: 80rpx;
  line-height: 80rpx;
}

.list-name {
  position: relative;
  font-size: 28rpx;
  padding: 15rpx;
  padding-left: 30rpx;
  color: #999;
}

.list-name.border::after {
  content: "";
  position: absolute;
  left: 30rpx;
  right: 0;
  top: 0;
  height: 1px;
  background: #f5f5f5;
}

.list-right-wrapper {
  position: absolute;
  right: 0;
  top: 50%;
  right: 20rpx;
  padding: 20rpx 0;
  z-index: 999;
  transform: translateY(-50%);
  background: #ddd;
  border-radius: 40rpx;
  box-sizing: border-box;
  text-align: center;
}

.right-item {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 2rpx 10rpx;
  font-size: 40rpx;
  color: #666;
}
.icon48{
  font-size: 56rpx;
}
.right-item.active {
  color: #ff9900;
}
.list-search {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
  width: 100%;
  height: 90rpx;
  padding: 10rpx 30rpx;
  box-sizing: border-box;
  z-index: 20;
  background: #FFF;
  border-bottom:1px #f5f5f5 solid; 
}

.search-title {
  flex-shrink: 0;
  font-size: 28rpx;
  padding-right: 10rpx;
}

.list-search-box {
  display: flex;
  align-items: center;
  padding: 0 30rpx;
  width: 100%;
  height: 70rpx;
  background: #f5f5f5;
  border-radius: 90rpx;
  font-size: 28rpx;
  box-sizing: border-box;
}

.list-search-box input {
  width: 100%;
  padding-left: 10rpx;
}

.search-button {
  flex-shrink: 0;
  height: 60rpx;
  line-height: 60rpx;
  font-size: 28rpx;
  margin-left: 10rpx;
}
.fiexed-box {
    position: absolute;
    top: 90rpx;
    z-index: 19;
    width: 100%;
}

/* new */
.index-brand-box{
    width: 100%;
    background-color: #F3F3F3;
    display: flex;
    justify-content: flex-start;
    flex-wrap: wrap;
    padding-left: 30rpx;
    box-sizing: border-box; 
}
.index-brand-box .index-brand-card{
  width: 148rpx;
  height: 164rpx;
  background-color: #fff;
  margin: 20rpx 30rpx 20rpx 0;
}
.index-brand-box .index-brand-card:nth-child(4n) {
  margin-right: 0;
}
.index-brand-box .index-brand-card .brand-img{
    width: 100%;
    height: 102rpx;
    padding: 10rpx;
    border-bottom: 2rpx solid #ededed;
    box-sizing: border-box;
}
.index-brand-box .index-brand-card .brand-pic{
  width: 100%;
  height: 100%;
}
.index-brand-box .index-brand-card .brand-name{
  width: 100%;
  height: 60rpx;
  line-height: 60rpx;
  text-align: center;
}
.index-brand-item{
    width: 100%;
    height: 80rpx;
    background-color: #fff;
    padding: 0 30rpx;
    border-bottom: 2rpx solid #f2f2f2;
    box-sizing: border-box;
}
.dflex-start{
  display: flex;
  justify-content: flex-start;
  align-items: center;
  color: #000;
}
.index-brand-item .brand-img{
  width: 100rpx;
  height: 80rpx;
  background-color: chartreuse;
  margin-right: 30rpx;
}

/* 无数据  */
.nodata {
  padding-top: 200rpx;
  text-align: center;
  font-size: 32rpx;
  color: #ddd;
}

调用

.js

var _default =
   {
     data: function data() {
       return {
        indexHeight: 0,
        queryBrandName: "",
        brandList: [
          { key: "HOT", list: [
            { img:"/static/img/brand/geli.png", brandName:"格力" },
            { img:"/static/img/brand/meidi.png", brandName:"美的" },
            { img:"/static/img/brand/feilipu.png", brandName:"飞利浦" },
            { img:"/static/img/brand/shenling.png", brandName:"申菱" },
            { img:"/static/img/brand/geli.png", brandName:"格力" },
            { img:"/static/img/brand/meidi.png", brandName:"美的" },
            { img:"/static/img/brand/feilipu.png", brandName:"飞利浦" },
            { img:"/static/img/brand/shenling.png", brandName:"申菱" }
          ]},
          { key: "M", list: [
            { img:"/static/img/brand/meidi.png", brandName:"美的" },
            { img:"/static/img/brand/meibo.png", brandName:"美博" }
          ]},
          {
            key: "G", list: [
              { img:"/static/img/brand/geli.png", brandName:"格力" },
              { img:"/static/img/brand/gelanshi.png", brandName:"格兰仕" }
            ]
          },
          {
            key: "T", list: [
              { img:"/static/img/brand/tcl.png", brandName:"TCL" }
            ]
          },
          {
            key: "S", list: [
              { img:"/static/img/brand/shenling.png", brandName:"申菱" },
              { img:"/static/img/brand/shenling.png", brandName:"申菱" },
              { img:"/static/img/brand/shenling.png", brandName:"申菱" },
              { img:"/static/img/brand/shenling.png", brandName:"申菱" },
              { img:"/static/img/brand/shenling.png", brandName:"申菱" },
              { img:"/static/img/brand/shenling.png", brandName:"申菱" },
              { img:"/static/img/brand/shenling.png", brandName:"申菱" },
              { img:"/static/img/brand/shenling.png", brandName:"申菱" },
              { img:"/static/img/brand/shenling.png", brandName:"申菱" },
              { img:"/static/img/brand/shenling.png", brandName:"申菱" },
              { img:"/static/img/brand/shenling.png", brandName:"申菱" },
              { img:"/static/img/brand/shenling.png", brandName:"申菱" },
              { img:"/static/img/brand/shenling.png", brandName:"申菱" },
              { img:"/static/img/brand/shenling.png", brandName:"申菱" }
            ]
          },
          {
            key: "Z", list: [
              { img:"/static/img/brand/zhuoli.png", brandName:"卓立" }
            ]
          },
          {
            key: "3", list: [
              { img:"/static/img/brand/sanling.png", brandName:"三菱" },
            ]
          }
        ]

       };

     },
     onl oad: function onl oad(option) {
        const _this = this;
        uni.getSystemInfo({
          success:function(res){      
            let windowHeight = res.windowHeight;
            _this.indexHeight =  windowHeight > 0 ? (windowHeight - 10) * 2 : 0;    
          }
        });
     },  
     methods: {
      toSearch: function toSearch(e){
        console.log('查询品牌名称', e)
        this.brandList = [
          {
            key: "T", list: [
              { img:"/static/img/brand/tcl.png", brandName:"TCL" }
            ]
          }
        ]
      },
      toBrand: function toBrand(e) {
        console.log('选择品牌',e.detail);
      }
     } 
    };

.json

{
    "navigationBarTitleText": "选择品牌",
    "navigationBarBackgroundColor": "#f1f1f1",
    "onReachBottomDistance": 50,
    "usingComponents": {
        "index-list": "../../../components/index-brand/index"
    }
}

.wxml

<view>
    <view class='wrapper' style="{{'height:'+indexHeight +'rpx;'}}"> 
        <index-list data="{{brandList}}" 
        data-event-opts="{{[['brand',[['toBrand',['$event']]]]]}}" bindbrand="__e"></index-list>
    </view>
</view>

.wxss

@charset "UTF-8";

page { background-color: #f1f1f1; }

.wrapper{
  width: 100%;
  background-color: #fff;
}

标签:详述,index,img,brand,索引,brandName,static,png
From: https://www.cnblogs.com/min77/p/17964124

相关文章

  • Blazor学习之旅:文章目录索引
    1Blazor学习路径微软学习社区(MicrosoftLearn)早在两三年前就推出了一门学习路径《使用Blazor构建Web应用程序》,我们可以学到如何通过BlazorWeb应用框架构建我们的第一个Web应用程序。我也是从2023年开始系统学习这个学习路径并形成了一个14篇推文组成的小系列文章。下面,我将......
  • Blazor学习之旅:文章目录索引
    1Blazor学习路径微软学习社区(MicrosoftLearn)早在两三年前就推出了一门学习路径《使用Blazor构建Web应用程序》,我们可以学到如何通过BlazorWeb应用框架构建我们的第一个Web应用程序。我也是从2023年开始系统学习这个学习路径并形成了一个14篇推文组成的小系列文章。下面,我将......
  • 用于PostgreSQL索引维护的有用查询
    PostgreSQL拥有丰富的索引功能,并且有很多文章解释索引的语法、用法和价值。在本文中,我将编写基本且有用的查询来查看数据库索引的状态。人们开发数据库一段时间后,当需要对软件架构进行更改时,他们忘记了以前的索引清理。这种方法会造成混乱,有时还会因为索引太多而降低数据库速度。......
  • 索引的一些总结
    索引的一些总结 1.1.1摘要如果说要对数据库进行优化,我们主要可以通过以下五种方法,对数据库系统进行优化。1.计算机硬件调优2.应用程序调优3.数据库索引优化4.SQL语句优化5.事务处理调优在本篇博文中,我们将想大家讲述数据库中索引类型和使用场合,本文以SQLServer......
  • 无涯教程-Redis - SELECT index 命令函数
    RedisSELECT命令用于选择具有指定的从零开始的数字索引的DB,新连接始终使用DB0。SELECT-返回值返回OKSELECT-语法以下是RedisSELECT命令的基本语法。redis127.0.0.1:6379>SELECTDB_INDEXSELECT-示例redis127.0.0.1:6379>SELECT1OKredis127.0.0.1:6......
  • 重新认识Elasticsearch-一体化矢量搜索引擎
    前言2023哪个网络词最热?我投“生成式人工智能”一票。过去一年大家都在拥抱大模型,所有的行业都在做自己的大模型。就像冬日里不来件美拉德色系的服饰就会跟不上时代一样。这不前段时间接入JES,用上好久为碰的RestHighLevelClient包。心血来潮再次访问Elasticsearch官网,发现风格又变......
  • 重新认识Elasticsearch-一体化矢量搜索引擎
    前言2023哪个网络词最热?我投“生成式人工智能”一票。过去一年大家都在拥抱大模型,所有的行业都在做自己的大模型。就像冬日里不来件美拉德色系的服饰就会跟不上时代一样。这不前段时间接入JES,用上好久为碰的RestHighLevelClient包。心血来潮再次访问Elasticsearch官网,发现风格又......
  • MySql 中 SUBSTRING_INDEX()用法
    SUBSTRING_INDEX()函数用于从一个指定分隔符分隔的字符串中提取子串。它返回一个字符串,包含在原始字符串中出现在指定分隔符之前或之后的所有字符。以下是SUBSTRING_INDEX()函数的语法:SUBSTRING_INDEX(str,delim,count)其中,str是要分割的字符串;delim是指定的分隔符;count......
  • ES 的跨索引查询详细讲解(转)
    转自:https://www.jianshu.com/p/b9a07bfb766a序言Elasticsearch,中文名直译弹性搜索,不仅仅在单索引内部分片层面弹性搜索,更强的是在跨索引外围支持分片弹性搜索,同比其它分布式数据产品,此特性更鲜明,代表了Elastic集群架构设计的优越性。本文将从以下几个方面展开探讨:为什么需......
  • 两个Mysql唯一索引的交换: 避免重复索引 Duplicate entry '3' for key 'priority_UNIQ
    需求我做了一个排行榜,但是主键是pid,不是排名,排名作为唯一索引,两个人排名交换,只需要交换排名唯一索引值即可.但是直接单独更新提示错误:Duplicateentry'3'forkey'priority_UNIQUE'方法本来希望可以在一条SQL语句中交换两个唯一索引值,但是发现这是不可能的,因为值......