作者:王国菊

前言

List是用来显示列表的组件,包含一系列相同宽度的列表项,适合连续、多行地呈现同类数据。本文将使用list组件实现字母索引地区列表和可折叠地区列表。

<list-item-group>是<list>的子组件,实现列表分组功能,不能再嵌套<list>,可以嵌套<list-item>。

<list-item>是<list>的子组件,展示列表的具体项。

效果展示

1、字母索引导航到列表对应位置。

2、列表滑动时也同步定位到字母索引处。

3、点击打开折叠的城市名称,再次点击收起当前列表。 demo.gif

list

list组件通常用于列表包含一系列相同宽度的列表项。list的子组件仅支持list-item-group和list-item

list 属性展示

名称 类型 默认值 必填 描述
scrollpage boolean false 设置为true时,将 list 顶部页面中非 list 部分随 list 一起滑出可视区域,当list方向为row时,不支持此属性。
cachedcount number 长列表延迟加载时list-item最少缓存数量。 可视区域外缓存的list-item数量少于该值时,会触发requestitem事件。
scrollbar string off 侧边滑动栏的显示模式(当前只支持纵向): - off:不显示。 - auto:按需显示(触摸时显示,2s后消失)。 - on:常驻显示。
scrolleffect string spring 滑动效果,目前支持如下滑动效果: - spring:弹性物理动效,滑动到边缘后可以根据初始速度或通过触摸事件继续滑动一段距离,松手后回弹。 - fade:渐隐物理动效,滑动到边缘后展示一个波浪形的渐隐,根据速度和滑动距离的变化渐隐也会发送一定的变化。 - no:滑动到边缘后无效果。
indexer boolean | Array<string> false 是否展示侧边栏快速字母索引栏。设置为true或者自定义索引时,索引栏会显示在列表右边界处。示例: "indexer" : "true"表示使用默认字母索引表。 "indexer" : "false"表示无索引。 "indexer" : ['#',‘1’,'2',‘3’,'4',‘5’,'6',‘7’,'8']表示自定义索引表。自定义时"#"必须要存在。 > ![icon-note.gif] 说明: > - indexer属性生效需要flex-direction属性配合设置为column,且columns属性设置为1。 >  > - 点击索引条进行列表项索引需要list-item子组件配合设置相应的section属性。
indexercircle<sup>5+</sup> boolean - 是否为环形索引。 穿戴设备默认为true,其他为false。indexer为false时不生效。
indexermulti<sup>5+</sup> boolean false 是否开启索引条多语言功能。 indexer为false时不生效。
indexerbubble<sup>5+</sup> boolean true 是否开启索引切换的气泡提示。 indexer为false时不生效。
divider<sup>5+</sup> boolean false item是否自带分隔线。 其样式参考样式列表的divider-color、divider-height、divider-length、divider-origin。
shapemode string default 侧边滑动栏的形状类型。 - default:不指定,跟随主题; - rect:矩形; - round:圆形。
updateeffect boolean false 用于设置当list内部的item发生删除或新增时是否支持动效。 - false:新增删除item时无过渡动效。 - true:新增删除item时播放过程动效。
chainanimation<sup>5+</sup> boolean false 用于设置当前list是否启用链式联动动效,开启后列表滑动以及顶部和底部拖拽时会有链式联动的效果。链式联动效果:list内的list-item间隔一定距离,在基本的滑动交互行为下,主动对象驱动从动对象进行联动,驱动效果遵循弹簧物理动效。 - false:不启用链式联动 - true:启用链式联动   > ! 说明:   > - 不支持动态修改。   > - 如同时配置了indexer,链式动效不生效。   > - 如配置了链式动效,list-item的sticky不生效。
initialindex number 用于设置当前List初次加载时视口起始位置显示的item,默认为0,即显示第一个item,如设置的序号超过了最后一个item的序号,则设置不生效,当同时设置了initialoffset属性时,当前属性不生效。当indexer为true或者scrollpage为true时,不生效。
initialoffset <length> 用于设置当前List初次加载时视口的起始偏移量,偏移量无法超过当前List可滑动的范围,如果超过会被截断为可滑动范围的极限值。当indexer为true或者scrollpage为true时,不生效。
selected<sup>5+</sup> string - 指定当前列表中被选中激活的项,可选值为list-item的section属性值。

主要知识点

列表容器(List):该组件从API version 4开始支持。

循环渲染( for ):默认$item代表数组中的元素, $idx代表数组中的元素索引。

字母索引条(indexer) : "indexer" : "true" 表示使用默认字母索引表。

实现思路

1、城市列表布局主要结构

属性 描述
listData 城市数据
type list-item类型,默认值为default,同一list中可以包含多种type的list-item,相同type的list-item需要确保渲染后的视图布局也相同,如果type固定,则使用show属性代替if属性,确保视图布局不变。
section 当前item的匹配字符串,如不设置则为空。不支持动态修改。group内只有主item设置有效。
groupcollapse和groupexpand groupcollapse和groupexpand事件仅支持list-item-group组件使用
// 索引城市列表
<list class="list" indexer="true" >
    <list-item class="item"  for="{{listData}}" type="{{$item.section}}" section="{{$item.pinyin}}">
        <div class="container" >
            <div class="in-container" >
                <text class="name">{{$item.name}}</text>
            </div>
        </div>
    </list-item>
</list>
// 折叠城市列表
<list style="width: 100%;" id="mylist">
            <list-item-group style="background-color: #fff;padding: 0;" for="listgroup in list" id="{{listgroup.name}}" ongroupcollapse="collapse" ongroupexpand="expand">
                <list-item class="list-item"  type="item"  for="listitem in listgroup.list" @click="childData">
                    <div class="item-group-child" >
                        <div class="child-list">
                            <text>{{listitem.name}}</text>
                        </div>
                    </div>
                </list-item>
                <list-item type="item"  primary="true">
                    <div class="item-group-child parent-child">
                        <text>{{listgroup.name}}</text>
                    </div>
                </list-item>
            </list-item-group>
        </list>

2、列表数据格式

索引字母城市列表数据

[
    {"name":"北京","pinyin":"BeiJing","id":110100},
    {"name":"天津","pinyin":"TianJin","id":120100},
    {"name":"石家庄","pinyin":"ShiJiaZhuang","id":130100},
    {"name":"唐山","pinyin":"TangShan","id":130200}
    ......
]

折叠城市列表数据

[
     {
        "id" : 140000,
        "list" : [
            {
                "id" : 140100,
                "list" : [
                    {
                        "id" : "140105",
                        "name" : "小店",
                        "pinyin" : "XiaoDian"
                    },
                    {
                        "id" : "140106",
                        "name" : "迎泽",
                        "pinyin" : "YingZe"
                    },
                    {
                        "id" : "140107",
                        "name" : "杏花岭",
                        "pinyin" : "XingHuaLing"
                    },
                    {
                        "id" : "140108",
                        "name" : "尖草坪",
                        "pinyin" : "JianCaoPing"
                    },
                    {
                        "id" : "140109",
                        "name" : "万柏林",
                        "pinyin" : "WanBaiLin"
                    },
                    {
                        "id" : "140110",
                        "name" : "晋源",
                        "pinyin" : "JinYuan"
                    },
                    {
                        "id" : "140121",
                        "name" : "清徐",
                        "pinyin" : "QingXu"
                    },
                    {
                        "id" : "140122",
                        "name" : "阳曲",
                        "pinyin" : "YangQu"
                    },
                    {
                        "id" : "140123",
                        "name" : "娄烦",
                        "pinyin" : "LouFan"
                    },
                    {
                        "id" : "140181",
                        "name" : "古交",
                        "pinyin" : "GuJiao"
                    }
                ],
                "name" : "太原",
                "pinyin" : "TaiYuan"
            },
    ......
]

3、处理数据

城市数据较多,此处单独放到一个文件中,使用import导入后使用。

// 初始化数据
import * as info from '../../common/city.js'
export default {
    data: {
        listData:[],
    },
    onInit() {

        let cityData = info.default.city;
        let citylist = [];
        cityData.forEach(item => {
            item.list.forEach(itemChild => {
                let obj = {
                    name: itemChild.name,
                    pinyin: itemChild.pinyin,
                    id: itemChild.id,
                }
                citylist.push(obj)
            });
        });
        this.listData = citylist;
    },
}

4、字母索引导航

巧妙地结合 API 提供的indexer:是否展示侧边栏快速字母索引栏。设置为true或者自定义索引时,索引栏会显示在列表右边界处,点击索引条进行列表项索引需要list-item子组件配合设置相应的section属性。

section:当前item的匹配字符串,如不设置则为空。不支持动态修改。group内只有主item设置有效。

项目源码

https://gitee.com/YiRanRuMeng/harmony-os-region-selecter

总结

此组件主要用于地区选择或者地区展示:使用list组件时需注意:

  • section:当前item的匹配字符串,如不设置则为空。不支持动态修改。group内只有主item设置有效。
  • groupcollapse和groupexpand事件仅支持list-item-group组件使用。
  • indexer属性生效需要flex-direction属性配合设置为column,且columns属性设置为1。

更多原创内容请关注:中软国际 HarmonyOS 技术团队

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com/#bkwz