React&Redux中Scroll List封裝實踐

一直直在寫一個前端項目,來分享一些Scroll封裝的實踐

設計目標

由於項目中須要大量的相似Scroll List,ListView頁面:前端

clipboard.png

github上看了圈感受沒有特別喜歡的,就本身來封裝了一下
層次結構以下:react

|-Scroll//主要處理諸以下拉刷新,上拉加載,加載狀態,錯誤信息等
|-----List //主要是List主體 
|--------ListEl //返回List裏單個Component,

使用方式

能夠像這樣簡潔的使用這個封裝的Scroll List(or List View)
有種來到了開發Windows RT、WPF使用ListView template的即視感git

<Scroll
        firstLoading={foo.FirstLoading}
        fistLoading={foo.ListLoading}
        isEnd={foo.isEnd}
        isFetch={foo.isFetch}
        fetchFailed={foo.fetchFailed}
        failedMag={foo.failedMag}
    >
        <List
            entities={coursecate.entities}
            result={coursecate.result}
            type={'samllCourseCate'}
        >
        </List>
    </Scroll>

開始封裝

說明:JSON格式扁平化(normalizr)

我在項目中使用normalizer來格式扁平化JSON數據github

開發複雜的應用時,不可避免會有一些數據相互引用。建議你儘量地把 state 範式化,不存在嵌套。把全部數據放到一個對象裏,每一個數據以 ID 爲主鍵,不一樣數據相互引用時經過 ID 來查找。把 應用的 state 想像成數據庫 。這種方法在 normalizr 文檔裏有詳細闡述。
normalizr:將嵌套的JSON格式扁平化,方便被Redux利用;
舉個例子
[{
  id: 1,
  title: 'Some Article',
  author: {
    id: 1,
    name: 'Dan'
  }
}, {
  id: 2,
  title: 'Other Article',
  author: {
    id: 1,
    name: 'Dan'
  }
}]

處理後會變成數據庫

{
  result: [1, 2],
  entities: {
    articles: {
      1: {
        id: 1,
        title: 'Some Article',
        author: 1
      },
      2: {
        id: 2,
        title: 'Other Article',
        author: 1
      }
    },
    users: {
      1: {
        id: 1,
        name: 'Dan'
      }
    }
  }
}

CommonScorll.js

import React, { PropTypes, Component } from 'react';

class CommonScorll extends Component {
    constructor(props) {
        super(props);
        const {FirstLoading,ListLoading} =this.props;
        this.ListScroll=this.ListScroll.bind(this);
        this.FirstLoading=()=>FirstLoading();
        this.ListLoading=()=>ListLoading();
    }
    componentDidMount() {
        console.log('common scroll componentDidMount')       
        //下拉刷新監聽綁定
        window.addEventListener('scroll', this.ListScroll);
        //初次Load
        this.FirstLoading;
    }
    componentWillUnmount(){
        //移除監聽
        window.removeEventListener('scroll', this.ListScroll);
    }
    ListScroll(e) {
        var scrollTop = document.body.scrollTop; 
        var offsetHeight = document.body.offsetHeight; 
        var scrollHeight = document.body.scrollHeight; 
        if (scrollTop >= scrollHeight - offsetHeight) { 
             this.ListLoading;
        } 
    }
    render(){
        console.log('common scroll render')
        const {
            isFetch,
            isEnd,
            fetchFailed,
            failedMsg,
            EmptyElement
                }=this.props;
        let NoMore=();
        if(isEnd){
            NoMore=(
                ...
            );
        }
        ...//根據你的需求處理 底部如:加載更多,加載失敗時從新加載等
        
        return(
            <div >
               {this.props.children}//由於List主體是被包裹在Scroll中的,因此加載children
               ...    
            </div>
        );
    }

}

export default CommonScorll;

CommonList.js

import React, { PropTypes, Component } from 'react';
import {ListEl} from './ListEl'

class CommonList extends Component {
    constructor(props) {
        super(props);
    }
    componentDidMount() {
        console.log('common list componentDidMount')       
    }
    render(){
            console.log('common list render')
            const {
                    entities,
                    result,
                    type
                    }=this.props;
                    //數據通過normalize格式化
            let datas=[<div key=0/>];
            if(result.length!==0){
                datas=[];
                result.forEach(function(id) {
                    datas.push(ListEl(id,entities,type))//ListEl是一個function 
                })
            }
            return(
                <div>
                    {datas}
                </div>
            );
        }
}

export default CommonList;

ListEl.js

import React, { PropTypes, Component } from 'react';
import SmallCourseCate from '../Common/CourseCate/SmallCourseCate'

export function ListEl(id,entites,type) {
    switch (type) {
        case 'samllCourseCate':
            if(entites.coursecates[id]){
                let coursecate=entites.coursecates[id];
                return(
                    <SmallCourseCate
                        key={id}
                        coursecate={coursecate}
                    />
                )
            }else{
                return (
                    <div>
                    <p>small coursecate el try get coursecate is null</p>
                    </div>
                )
            }
        ...
        default:
        return (
            <div>
                <p>el type undefind</p>
            </div>
        )
    }
}

總結&TODO

  1. 封裝後整體Scroll List比較優雅和快捷
  2. 可是欠缺性能優化,使用immutable、shouldComponentUpdate優化性能
相關文章
相關標籤/搜索