1. 程式人生 > 其它 >react+taro小程式:手風琴式卡片的動態實現

react+taro小程式:手風琴式卡片的動態實現

技術標籤:前端react小程式

目錄

問題描述

背景:實現教務小程式的一個空教室查詢的展示面板。
環境: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. 待解決問題

這種實現是通過對全部元件開閉狀態進行更新實現的。很明顯,效率很低,有沒有效率高的解決辦法,歡迎留言交流。