react+taro小程序:手风琴式卡片的动态实现

问题描述

背景:实现教务小程序的一个空教室查询的展示面板。
环境:Taro小程序+React+TaroUI
实现目标:卡片式手风琴,移步文章末尾查看效果图。只注重功能,界面待完善
问题

  1. 手风琴卡片的实现
  2. 根据传参,决定添加卡片的数量
  3. 默认情况下,针对手风琴的展开和闭合状态,是一开全开一闭全闭

1. 手风琴卡片的实现

第一步:将手风琴的AtAccordion套入AtCard;
第二步:在手风琴的AtList下套AtCard。

<AtCard>
 <AtAccordion
        open={this.state.open}
        onClick={this.handleClick.bind(this)}
        title='标题一'
      >
        <AtList hasBorder={false}>
          <AtCard
          note='小Tips'
          extra='额外信息'
          title='这是个标题'
          thumb='http://www.logoquan.com/upload/list/20180421/logoquan15259400209.PNG'
        >
          这也是内容区 可以随意定义功能
        </AtCard>
        <AtCard
          note='小Tips'
          extra='额外信息'
          title='这是个标题'
          thumb='http://www.logoquan.com/upload/list/20180421/logoquan15259400209.PNG'
        >
          这也是内容区 可以随意定义功能
        </AtCard>
        </AtList>
      </AtAccordion>
    </AtCard>

2. 动态决定卡片个数

这一步前前后后做了很多更改,就不再赘述中间错误的尝试过程。

2.1 原始数据的处理

原始数据如下,在json里不能直观的获取key,json也难以实现遍历,所以我们对其修改

{
//[教室,教室容量]
"A6": [
  [201, 30]
  [202, 30]
  [206, 60]
],
  "A5":[
  [301, 30]
  [302, 30]
  [306, 60]
]  }

修改后我们可以通过key来索引value,通过map就可快速的遍历

[
      {
        "build": "A1",
        "classrooms": [["19", "40"], ["183", "80"], ["145", "120"]],
      },
      {
        "build": "A2",
        "classrooms": [["319", "80"], ["483", "30"], ["5545", "120"]],
      },
      {
        "build": "A3",
        "classrooms": [["319", "80"], ["483", "30"], ["5545", "120"]],
      },
      {
        "build": "A4",
        "classrooms": [["319", "80"], ["483", "30"], ["5545", "120"]],
      },
      {
        "build": "A5",
        "classrooms": [["319", "80"], ["483", "30"], ["5545", "120"]],
      }
    ]

2.2 二重map遍历实现动态添加组件

这里注意到map的参数是带下划线的,不带下划线不能用,虽然解决了但不太清楚为什么

          <View>
            {
              this.state.classes.map((build, index) => {
                return (
                  <View>
                    <AtCard>
                      <AtAccordion
                        open={this.state.open[index]}
                        onClick={(value)=>this.state.open=value}
                        // onClick={this.handleClick.bind(this, index)}
                        title={build["build"]}><AtList hasBorder={false}>
                          {
                            build["classrooms"].map((_classroom) => {
                              return (
                                <AtCard
                                  note={'教室' + _classroom[0]}
                                  extra={'教室容量:' + _classroom[1] + '人'}
                                  title={_classroom[0]}
                                  thumb='http://www.logoquan.com/upload/list/20180421/logoquan15259400209.PNG'
                                ></AtCard>)
                            }
                            )
                          }
                        </AtList>
                      </AtAccordion>
                    </AtCard>
                  </View>)
              })
            }
          </View>

3.手风琴单独展开闭合问题

参考@黑夜d星辰大佬的博客,实现了组件单独展开。但是又存在新的问题:只能单独展开一个。
原因:通过对所有open状态进行更新,目标open设为组件传过来的value,非目标更新为关闭。
解决办法:拷贝原有open,对原有open 进行更改。

  handleClick(id, value) {
    let open_T = this.state.open;
    for (let i = 0; i < this.state.buildingNum; i++) {
      if (i === id) {
        open_T[i] = value
      }
    }
    this.setState({
      open: open_T
    })
  }

4.完整源码

import { AtAccordion, AtList, AtListItem, AtCard } from 'taro-ui'
import Taro from '@tarojs/taro'
import React, { Component } from 'react'
import { View, Image, Text } from '@tarojs/components'
import EmptyImg from '../../../assets/img/empty.svg'


export default class Index extends Component {
  constructor(props) {
    super(props)
    this.state = {
      open: [],
      classes: [],
      buildingNum: '',
    }
  }
  componentWillMount() {
    Taro.setNavigationBarColor({
      frontColor: '#ffffff',
      backgroundColor: "#3374ff",
      fail: (err) => {
        console.log(err)
      }
    })
  }
  componentDidMount() {
    var classes = [
      {
        "build": "A1",
        "classrooms": [["19", "40"], ["183", "80"], ["145", "120"]],
      },
      {
        "build": "A2",
        "classrooms": [["319", "80"], ["483", "30"], ["5545", "120"]],
      },
      {
        "build": "A3",
        "classrooms": [["319", "80"], ["483", "30"], ["5545", "120"]],
      },
      {
        "build": "A4",
        "classrooms": [["319", "80"], ["483", "30"], ["5545", "120"]],
      },
      {
        "build": "A5",
        "classrooms": [["319", "80"], ["483", "30"], ["5545", "120"]],
      }
    ]
    this.setState({
      classes: classes,
      buildingNum: classes.length,
    })
  }
  
  handleClick(id, value) {
    let open_T = this.state.open;
    for (let i = 0; i < this.state.buildingNum; i++) {
      if (i === id) {
        open_T[i] = value
      }
    }
    this.setState({
      open: open_T
    })
  }

  render() {
    return (
      <View>
        {this.state.classes === 0 ?
          <View className='grade-none'>
            <Image
              src={EmptyImg}
              className='grade-none-noneImg'
            />
            <Text className='grade-none-noneText'>没有查询到空教室~</Text>
            <View className='grade-none-ad'></View>
          </View>
          :
          <View>
            {
              this.state.classes.map((build, index) => {
                return (
                  <View>
                    <AtCard>
                      <AtAccordion
                        open={this.state.open[index]}
                        onClick={this.handleClick.bind(this, index)}
                        title={build["build"]}><AtList hasBorder={false}>
                          {
                            build["classrooms"].map((_classroom) => {
                              return (
                                <AtCard
                                  note={'教室' + _classroom[0]}
                                  extra={'教室容量:' + _classroom[1] + '人'}
                                  title={_classroom[0]}
                                  thumb='http://www.logoquan.com/upload/list/20180421/logoquan15259400209.PNG'
                                ></AtCard>)
                            }
                            )
                          }
                        </AtList>
                      </AtAccordion>
                    </AtCard>
                  </View>)
              })
            }
          </View>}
      </View >
    )
  }
}

5.界面效果

在这里插入图片描述

6. 待解决问题

这种实现是通过对全部组件开闭状态进行更新实现的。很明显,效率很低,有没有效率高的解决办法,欢迎留言交流。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值