一直直在写一个前端项目,来分享一些Scroll封装的实践
由于项目中须要大量的相似Scroll List,ListView页面:前端
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>
我在项目中使用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' } } } }
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;
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;
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> ) } }