先放项目地址:https://github.com/1067011734/balibali

感谢无私的程序员们分享

我们边看效果边看代码

项目运行出来的效果



先看Home页面

轮播

  1. //src\pages\Home\model\Carousel.js
  2. import React, { Component } from 'react'
  3. import { Carousel } from 'antd-mobile'
  4. import img from '@/images/banner/1.jpg'
  5. import img2 from '@/images/banner/2.jpg'
  6. import img3 from '@/images/banner/3.jpg'
  7. class app extends Component {
  8. state = {
  9. data: ['1', '2', '3'],
  10. imgHeight: 176,
  11. }
  12. componentDidMount() {
  13. // simulate img loading
  14. setTimeout(() => {
  15. this.setState({
  16. data: [img, img2, img3],
  17. });
  18. }, 100);
  19. }
  20. render() {
  21. return (
  22. <Carousel
  23. autoplay={false}
  24. infinite
  25. beforeChange={(from, to) => console.log(`slide from ${from} to ${to}`)}
  26. afterChange={index => console.log('slide to', index)}
  27. >
  28. {this.state.data.map((val, index) => (
  29. <a
  30. key={index}
  31. style={{ display: 'inline-block', width: '100%', height: this.state.imgHeight }}
  32. >
  33. <img
  34. src={val}
  35. alt="val"
  36. style={{ width: '100%', verticalAlign: 'top', height: this.state.imgHeight }}
  37. onLoad={() => {
  38. // fire window resize event to change height
  39. // 若用非手机模式打开,imgheight会因为整个浏览器的长度100%自适应造成100%全屏,手机模式加载则没影响
  40. window.dispatchEvent(new Event('resize'));
  41. this.setState({ imgHeight: 'auto' })
  42. }}
  43. />
  44. </a>
  45. ))}
  46. </Carousel>
  47. )
  48. }
  49. }
  50. export default app



这里也是封装成组件做的

  1. //src\components\Card\index.js
  2. import React, { Component } from 'react'
  3. import PropTypes from 'prop-types'
  4. import style from './index.less'
  5. class app extends Component {
  6. PropTypes={
  7. list: PropTypes.array,
  8. className:PropTypes.string,
  9. }
  10. static defaultProps ={
  11. list :[],
  12. }
  13. state = {
  14. }
  15. componentDidMount(){
  16. }
  17. componentWillReceiveProps(nextProps){
  18. }
  19. close=()=>{
  20. this.setState({open:false})
  21. this.props.onClose()
  22. }
  23. render() {
  24. const {list,className} = this.props
  25. return (
  26. <div className={`${style["card-wrap"]} ${className}`}>
  27. {
  28. list.map((x,index)=>(
  29. <div className={style.card} key={index}>
  30. <div className="card-img">
  31. <img src={x.src} alt="" />
  32. </div>
  33. <div className="title">
  34. {x.title}
  35. </div>
  36. </div>
  37. ))
  38. }
  39. </div>
  40. )
  41. }
  42. }
  43. export default app

看整体的代码是这个

  1. //src\pages\Home\index.js
  2. import React, { Component } from 'react'
  3. import { InputItem, Button, WhiteSpace, WingBlank, NoticeBar } from 'antd-mobile'
  4. //轮播组件
  5. import Carousel from './model/Carousel'
  6. import Card from '@/components/Card'
  7. import img from '@/images/moon.png'
  8. class app extends Component {
  9. state = {
  10. title: '欢迎来到叭哩叭哩,github-https://github.com/1067011734/balibali!!!!'
  11. }
  12. cardList = [
  13. { title: '团员中秋', src: img },
  14. { title: '团员中秋', src: img },
  15. { title: '团员中秋', src: img },
  16. { title: '团员中秋', src: img },
  17. { title: '团员中秋', src: img },
  18. { title: '团员中秋', src: img },
  19. { title: '团员中秋', src: img },
  20. { title: '团员中秋', src: img },
  21. { title: '团员中秋', src: img },
  22. { title: '团员中秋', src: img },
  23. { title: '团员中秋', src: img },
  24. { title: '团员中秋', src: img },
  25. ]
  26. render() {
  27. const { title } = this.state
  28. return (
  29. <div className="page">
  30. <NoticeBar marqueeProps={{ loop: true, style: { padding: '0 7.5px' } }}>
  31. {title}
  32. </NoticeBar>
  33. <Carousel />
  34. <Card list={this.cardList}/>
  35. </div>
  36. )
  37. }
  38. }
  39. export default app

在index.js中我们引用app

  1. //src\pages\index.js
  2. import React, { Component } from 'react'
  3. import { connect } from 'dva'
  4. import Transiton from '@/components/Transition'
  5. import '@/styles/base.less'
  6. class app extends Component {
  7. state = {
  8. }
  9. componentDidMount(){
  10. }
  11. render() {
  12. return (
  13. <Transiton {...this.props}>
  14. {this.props.children}
  15. </Transiton>
  16. )
  17. }
  18. }
  19. export default app
  1. //src\components\Transition\index.js
  2. import React, { Component } from 'react'
  3. import PropTypes from 'prop-types'
  4. import ReactCSSTransitionGroup from 'react-addons-css-transition-group'
  5. import StaticContainer from 'react-static-container'
  6. import style from './index.less'
  7. class app extends Component {
  8. PropTypes={
  9. open: PropTypes.bool,
  10. onClose: PropTypes.func,
  11. }
  12. state = {
  13. previousPathname:null,
  14. }
  15. componentWillMount() {
  16. document.body.style.margin = "0px";
  17. // 这是防止页面被拖拽
  18. document.body.addEventListener('touchmove', (ev) => {
  19. ev.preventDefault();
  20. });
  21. }
  22. componentWillReceiveProps(nextProps, nextContext) {
  23. if (nextProps.location.pathname !== this.props.location.pathname) {
  24. this.setState({ previousPathname: this.props.location.pathname })
  25. }
  26. }
  27. componentDidUpdate() {
  28. if (this.state.previousPathname) {
  29. this.setState({ previousPathname: null })
  30. }
  31. }
  32. render() {
  33. const {location,children,history} =this.props
  34. const {action} =history
  35. //goback:pop,push:push
  36. const className = action==='POP'?'translation-arrow-right':'translation-arrow-left'
  37. // const className = 'translation-arrow-left'
  38. const {pathname} =location
  39. const key = (pathname!=="/user")?'':"pathname"
  40. return (
  41. <ReactCSSTransitionGroup
  42. component="div"
  43. className={`translation-wrap ${className}`}
  44. transitionName="translation"
  45. transitionEnterTimeout={300}
  46. transitionLeaveTimeout={300}
  47. // transitionLeave={false}
  48. >
  49. {/* 用key控制滑动权限----- 苍天啊 */}
  50. <div key={key} className={`${pathname} translation-content`}>
  51. {children}
  52. </div>
  53. </ReactCSSTransitionGroup>
  54. )
  55. }
  56. }
  57. export default app

其实我很好奇,下面的切换页面在哪里

下面的是login页面

  1. //src\pages\Login.js
  2. import React, { Component } from 'react'
  3. import { InputItem, Button, WhiteSpace, Toast } from 'antd-mobile'
  4. import { createForm } from 'rc-form'
  5. import { connect } from 'dva'
  6. import { loginReg } from '@regularConfig'
  7. import style from '@/styles/login.less'
  8. import avataSrc from '@/images/icon/avatar.png'
  9. import loginUserSrc from '@/images/icon/login_user.png'
  10. import loginPassSrc from '@/images/icon/login_pass.png'
  11. @createForm()
  12. @connect(({ login, loading }) => ({
  13. login,
  14. submitting: loading.effects['login/login'],
  15. }))
  16. class app extends Component {
  17. state = {
  18. }
  19. submit = () => {
  20. const { getFieldProps, getFieldError } = this.props.form
  21. this.props.form.validateFields((error, values) => {
  22. if (error) {
  23. const msg = `请输入${getFieldError('user') || ''}${getFieldError('password') || ''}`
  24. Toast.info(msg, 1);
  25. return
  26. }
  27. // this.props.history.push({ pathname: '/home' })
  28. const { dispatch } = this.props
  29. dispatch({
  30. type: 'common/login',
  31. payload: {
  32. ...values,
  33. },
  34. })
  35. })
  36. }
  37. normalize = (val, prev) => {
  38. if (!loginReg.test(val)) {
  39. Toast.info('不能包含中文和大写', 1);
  40. return prev
  41. }
  42. return val
  43. }
  44. render() {
  45. let errors
  46. const { getFieldProps } = this.props.form
  47. return (
  48. <div className={`page ${style.login}`}>
  49. <div className={`${style["page-header"]}`}>
  50. <label>进入叭哩叭哩</label><img src={avataSrc} alt=""/>
  51. </div>
  52. <InputItem
  53. type="text"
  54. placeholder="账号为admin"
  55. maxLength="10"
  56. minLength="4"
  57. clear
  58. {...getFieldProps('user', {
  59. rules: [{ required: true, message: '账号', }],
  60. normalize: this.normalize,
  61. })}
  62. >
  63. <img src={loginUserSrc} className='icon' />
  64. </InputItem>
  65. <InputItem
  66. type="password"
  67. placeholder="密码为admin"
  68. maxLength="10"
  69. clear
  70. {...getFieldProps('password', {
  71. rules: [{ required: true, message: '密码', }],
  72. normalize: this.normalize
  73. })}
  74. >
  75. <img src={loginPassSrc} className='icon' />
  76. </InputItem>
  77. <WhiteSpace size="xl"/>
  78. <WhiteSpace size="xl"/>
  79. <Button type="primary" onClick={this.submit}>确定</Button>
  80. <WhiteSpace />
  81. </ div>
  82. )
  83. }
  84. }
  85. export default app

路由也是会骗人的

  1. //src\pages\404.js
  2. import React from 'react';
  3. import Link from 'umi/link';
  4. import Exception from '@/components/Exception';
  5. export default () => (
  6. <Exception type="404" style={{ minHeight: 500, height: '100%' }} linkElement={Link} />
  7. );

  1. //src\pages\User\index.js
  2. import React, { Component } from 'react'
  3. import { Steps,InputItem,Button,WhiteSpace} from 'antd-mobile'
  4. import Container from '@/components/Container'
  5. import { createForm } from 'rc-form'
  6. import { connect } from 'dva'
  7. import router from 'umi/router'
  8. import Step1 from './model/step1'
  9. import Step2 from './model/step2'
  10. import Step3 from './model/step3'
  11. const {Step} = Steps
  12. @createForm()
  13. @connect(({ common}) => ({
  14. userInfo:common.userInfo
  15. }))
  16. class app extends Component {
  17. state = {
  18. userInfo:{
  19. name:'', // 姓名
  20. dept:'', // 所属部门
  21. person:[], //个性标签
  22. avatar:"" //头像
  23. },
  24. stepNumber:1,
  25. }
  26. stepList=[
  27. {title:'基本设置',key:1},
  28. {title:'个性标签',key:2},
  29. {title:'上传头像',key:3},
  30. ]
  31. componentWillMount(){
  32. const {userInfo} = this.props
  33. this.setState({userInfo})
  34. }
  35. componentDidMount(){
  36. }
  37. // 步骤变化
  38. stepSwitch=(key)=>{
  39. const {userInfo} = this.state
  40. switch(key){
  41. case 1: return <Step1 onChange={this.changeData} userInfo={userInfo} />
  42. case 2: return <Step2 onChange={this.changeData} userInfo={userInfo} />
  43. case 3: return <Step3 onChange={this.changeData} userInfo={userInfo} />
  44. default: break;
  45. }
  46. }
  47. // 步骤完成保存数据
  48. changeData=(data,key)=>{
  49. const { dispatch } = this.props
  50. let {stepNumber,userInfo} = this.state
  51. stepNumber=key+1
  52. if(stepNumber>3){
  53. const params ={...userInfo,...data}
  54. dispatch({
  55. type: 'common/updateUserInfo',
  56. payload: params,
  57. })
  58. router.goBack()
  59. return
  60. }
  61. this.setState({
  62. userInfo:{...userInfo,...data},
  63. stepNumber,
  64. })
  65. }
  66. render() {
  67. const { getFieldProps, getFieldError } = this.props.form
  68. const {stepNumber} = this.state
  69. return (
  70. <Container title="个人设置">
  71. <Steps direction="horizontal">
  72. {this.stepList.map(item=><Step
  73. key={item.key}
  74. title={item.title}
  75. icon={<i className={`step-circle ${item.key<=stepNumber?'bj-primary':''}`}>{item.key<stepNumber?'√':item.key}</i>}
  76. status={item.key<stepNumber?'finish':'wait'}
  77. />)}
  78. </Steps>
  79. <WhiteSpace />
  80. {this.stepSwitch(stepNumber)}
  81. {/* <Step1 /> */}
  82. </Container>
  83. )
  84. }
  85. }
  86. export default app

  1. //src\pages\User\model\step1.js
  2. import React, { Component } from 'react'
  3. import { List, InputItem, Switch, Stepper, Range, Button, Picker, Toast } from 'antd-mobile'
  4. import Container from '@/components/Container'
  5. import { createForm } from 'rc-form'
  6. import PropTypes from 'prop-types'
  7. const { Item } = List
  8. @createForm()
  9. class app extends Component {
  10. PropTypes = {
  11. onChange: PropTypes.func,
  12. }
  13. state = {
  14. }
  15. componentDidMount() {
  16. const { userInfo } = this.props
  17. const { name, dept } = userInfo
  18. // debugger
  19. this.props.form.setFieldsValue({
  20. name,
  21. dept: [dept],
  22. })
  23. }
  24. onSubmit = () => {
  25. const { getFieldError } = this.props.form
  26. this.props.form.validateFields((error, values) => {
  27. if (error) {
  28. const msg = `请输入${getFieldError('name') || ''}${getFieldError('dept') || ''}`
  29. Toast.info(msg, 1);
  30. return
  31. }
  32. values.dept = values.dept[0]
  33. this.props.onChange(values, 1)
  34. })
  35. }
  36. validateAccount = (rule, value, callback) => {
  37. if (value && value.length > 0) {
  38. callback();
  39. } else {
  40. callback(new Error('At least four characters for account'));
  41. }
  42. }
  43. render() {
  44. const { getFieldProps, getFieldError } = this.props.form
  45. const deptData = [
  46. {
  47. label: '前端攻城狮',
  48. value: '前端攻城狮',
  49. },
  50. {
  51. label: 'java',
  52. value: 'java',
  53. },
  54. ]
  55. return (
  56. <form className="flex-column">
  57. <List className="flex-3">
  58. <InputItem
  59. {...getFieldProps('name', {
  60. rules: [{ required: true, message: '账号', }],
  61. }
  62. )}
  63. clear
  64. placeholder="请修改账号"
  65. >账号
  66. </InputItem>
  67. <Picker data={deptData} {...getFieldProps('dept',
  68. {
  69. rules: [{ required: true, message: '岗位', }],
  70. })}
  71. cols="1"
  72. >
  73. <List.Item arrow="horizontal">岗位</List.Item>
  74. </Picker>
  75. </List>
  76. <div className="flex-1">
  77. <Button type="primary" onClick={this.onSubmit}>下一步</Button>
  78. </div>
  79. </form>
  80. )
  81. }
  82. }
  83. export default app

  1. //src\pages\User\model\step2.js
  2. import React, { Component } from 'react'
  3. import { Tag ,Button } from 'antd-mobile'
  4. import { createForm } from 'rc-form'
  5. import PropTypes from 'prop-types'
  6. import ReactDOM from 'react-dom'
  7. @createForm()
  8. class app extends Component {
  9. PropTypes={
  10. onChange: PropTypes.func,
  11. }
  12. state = {
  13. }
  14. tagList=[
  15. '乐观','努力','积极','有爱心','勇敢','思想良好','积极向上','善于与相处','对工作积极','认真负责',
  16. '严格要求自己','有强烈的责任心'
  17. ]
  18. componentDidMount(){
  19. }
  20. onSubmit = () => {
  21. const domSelect= ReactDOM.findDOMNode(this).querySelectorAll(".am-tag-active")
  22. const selectArr = Array.from(domSelect,x=>x.textContent)
  23. this.props.onChange({person:selectArr},2)
  24. }
  25. render() {
  26. const {userInfo} = this.props
  27. const {person} = userInfo
  28. return (
  29. <div className="flex-column">
  30. <div className="flex-3">
  31. {this.tagList.map((x,index)=>
  32. <Tag key={index} selected={person&&person.includes(x)}>{x}</Tag>
  33. )}
  34. </div>
  35. <div className="flex-1">
  36. <Button type="primary" onClick={this.onSubmit}>下一步</Button>
  37. </div>
  38. </div>
  39. )
  40. }
  41. }
  42. export default app



//src\pages\User\model\step3.js

import React, { Component } from 'react'

import { ImagePicker ,Button } from 'antd-mobile'

import { createForm } from 'rc-form'

import PropTypes from 'prop-types'

@createForm()

class app extends Component {

PropTypes={

onChange: PropTypes.func,

}

  1. state = {
  2. files: [],
  3. }

componentDidMount(){

const {userInfo} = this.props

const {avatar} = userInfo

this.setState({files:[{url:avatar}]})

}

onSubmit = () => {

const {files} = this.state

this.props.onChange({avatar:files[0]?files[0].url:''},3)

}

onChange = (files, type, index) => {

console.log(files, type, index);

this.setState({

files,

})

}

  1. render() {
  2. const { files } = this.state
  3. return (
  4. <div className="flex-column">
  5. <div className="flex-3">
  6. <ImagePicker
  7. files={files}
  8. onChange={this.onChange}
  9. onImageClick={(index, fs) => console.log(index, fs)}
  10. selectable={files.length < 1}
  11. accept="image/gif,image/jpeg,image/jpg,image/png"
  12. />
  13. </div>
  14. <div className="flex-1">
  15. <Button type="primary" onClick={this.onSubmit}>保存</Button>
  16. </div>
  17. </div>
  18. )
  19. }

}

export default app

  1. ![](https://img2018.cnblogs.com/blog/1037363/201905/1037363-20190522180524238-1345634353.png)
  2. ```js
  3. //src\pages\Map\index.js
  4. import React, { Component } from 'react'
  5. import { createForm } from 'rc-form'
  6. import Bmap from '@/components/Bmap'
  7. import { connect } from 'dva'
  8. @createForm()
  9. @connect(({ login, loading }) => ({
  10. login,
  11. submitting: loading.effects['login/login'],
  12. }))
  13. class app extends Component {
  14. state = {
  15. }
  16. componentDidMount(){
  17. console.info(this.props)
  18. }
  19. render() {
  20. return (
  21. <div className="page">
  22. <Bmap />
  23. </div>
  24. )
  25. }
  26. }
  27. export default app
  1. //src\components\Bmap\index.js
  2. //定义地图组件
  3. import React, { Component } from 'react'
  4. import PropTypes from 'prop-types'
  5. import BMap from 'BMap'
  6. import style from './index.less'
  7. class app extends Component {
  8. PropTypes={
  9. info: PropTypes.string,
  10. }
  11. state = {
  12. info:'叭哩叭哩'
  13. }
  14. map={}
  15. componentDidMount () {
  16. const map = new BMap.Map("Bmap"); // 创建Map实例
  17. this.map=map
  18. this.mapInit(map)
  19. }
  20. mapInit=(map)=>{
  21. const _self = this
  22. map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);
  23. map.addControl(new BMap.MapTypeControl()); // 添加地图类型控件
  24. map.enableScrollWheelZoom(true); // 开启鼠标滚轮缩放
  25. // const top_left_control = new BMap.ScaleControl({anchor: BMAP_ANCHOR_TOP_LEFT});// 左上角,添加比例尺
  26. const top_left_navigation = new BMap.NavigationControl(); // 左上角,添加默认缩放平移控件
  27. // const top_right_navigation = new BMap.NavigationControl({anchor: BMAP_ANCHOR_TOP_RIGHT, type: BMAP_NAVIGATION_CONTROL_SMALL}); // 右上角,仅包含平移和缩放按钮
  28. // map.addControl(top_left_control);
  29. map.addControl(top_left_navigation);
  30. // map.addControl(top_right_navigation);
  31. // 定位
  32. const point = new BMap.Point(116.331398,39.897445);
  33. map.centerAndZoom(point,15);// 初始化地图,设置中心点坐标和地图级别
  34. const geolocation = new BMap.Geolocation();
  35. geolocation.getCurrentPosition(function(r){
  36. if(this.getStatus() == BMAP_STATUS_SUCCESS){
  37. const mk = new BMap.Marker(r.point);
  38. map.addOverlay(mk);
  39. map.panTo(r.point);
  40. _self.setWindowInfo(mk)
  41. // alert('您的位置:'+r.point.lng+','+r.point.lat);
  42. }
  43. else {
  44. // alert('failed'+this.getStatus());
  45. }
  46. },{enableHighAccuracy: true})
  47. }
  48. setWindowInfo=(marker)=>{
  49. const {info} = this.state
  50. marker.addEventListener("click",(e) => {
  51. this.openInfo(info,e)}
  52. );
  53. }
  54. // 创建并打开信息窗口
  55. openInfo=(content,e)=>{
  56. const opts = {
  57. width : 250, // 信息窗口宽度
  58. height: 80, // 信息窗口高度
  59. title : "信息窗口" , // 信息窗口标题
  60. enableMessage:true// 设置允许信息窗发送短息
  61. }
  62. const map =this.map
  63. const p = e.target;
  64. const point = new BMap.Point(p.getPosition().lng, p.getPosition().lat);
  65. const infoWindow = new BMap.InfoWindow(content,opts); // 创建信息窗口对象
  66. map.openInfoWindow(infoWindow,point); // 开启信息窗口
  67. }
  68. render() {
  69. return (
  70. <div className={style.bMap} id="Bmap" />
  71. )
  72. }
  73. }
  74. export default app

  1. //这个比较厉害,还有下拉加载刷新
  2. ```js
  3. //src\pages\Book\index.js
  4. import React, { Component } from 'react'
  5. import ReactDOM from 'react-dom'
  6. // import { InputItem,Button, WhiteSpace, WingBlank } from 'antd-mobile'
  7. // import data from './data'
  8. import { PullToRefresh, ListView, Button } from 'antd-mobile';
  9. const data = [
  10. {
  11. img: 'https://zos.alipayobjects.com/rmsportal/dKbkpPXKfvZzWCM.png',
  12. title: 'Meet hotel',
  13. des: '不是所有的兼职汪都需要风吹日晒',
  14. },
  15. {
  16. img: 'https://zos.alipayobjects.com/rmsportal/XmwCzSeJiqpkuMB.png',
  17. title: 'McDonald\'s invites you',
  18. des: '不是所有的兼职汪都需要风吹日晒',
  19. },
  20. {
  21. img: 'https://zos.alipayobjects.com/rmsportal/hfVtzEhPzTUewPm.png',
  22. title: 'Eat the week',
  23. des: '不是所有的兼职汪都需要风吹日晒',
  24. },
  25. ];
  26. const NUM_ROWS = 20;
  27. let pageIndex = 0;
  28. function genData(pIndex = 0) {
  29. const dataArr = [];
  30. for (let i = 0; i < NUM_ROWS; i++) {
  31. dataArr.push(`row - ${(pIndex * NUM_ROWS) + i}`);
  32. }
  33. return dataArr;
  34. }
  35. class app extends React.Component {
  36. constructor(props) {
  37. super(props);
  38. const dataSource = new ListView.DataSource({
  39. rowHasChanged: (row1, row2) => row1 !== row2,
  40. });
  41. this.state = {
  42. dataSource,
  43. refreshing: true,
  44. isLoading: true,
  45. height: document.documentElement.clientHeight,
  46. useBodyScroll: false,
  47. };
  48. }
  49. // If you use redux, the data maybe at props, you need use `componentWillReceiveProps`
  50. // componentWillReceiveProps(nextProps) {
  51. // if (nextProps.dataSource !== this.props.dataSource) {
  52. // this.setState({
  53. // dataSource: this.state.dataSource.cloneWithRows(nextProps.dataSource),
  54. // });
  55. // }
  56. // }
  57. componentDidUpdate() {
  58. if (this.state.useBodyScroll) {
  59. document.body.style.overflow = 'auto';
  60. } else {
  61. document.body.style.overflow = 'hidden';
  62. }
  63. }
  64. componentDidMount() {
  65. const hei = this.state.height - ReactDOM.findDOMNode(this.lv).offsetTop;
  66. setTimeout(() => {
  67. this.rData = genData();
  68. this.setState({
  69. dataSource: this.state.dataSource.cloneWithRows(genData()),
  70. height: hei,
  71. refreshing: false,
  72. isLoading: false,
  73. });
  74. }, 1500);
  75. }
  76. onRefresh = () => {
  77. this.setState({ refreshing: true, isLoading: true });
  78. // simulate initial Ajax
  79. setTimeout(() => {
  80. this.rData = genData();
  81. this.setState({
  82. dataSource: this.state.dataSource.cloneWithRows(this.rData),
  83. refreshing: false,
  84. isLoading: false,
  85. });
  86. }, 600);
  87. };
  88. onEndReached = (event) => {
  89. // load new data
  90. // hasMore: from backend data, indicates whether it is the last page, here is false
  91. if (this.state.isLoading && !this.state.hasMore) {
  92. return;
  93. }
  94. console.log('reach end', event);
  95. this.setState({ isLoading: true });
  96. setTimeout(() => {
  97. this.rData = [...this.rData, ...genData(++pageIndex)];
  98. this.setState({
  99. dataSource: this.state.dataSource.cloneWithRows(this.rData),
  100. isLoading: false,
  101. });
  102. }, 1000);
  103. };
  104. render() {
  105. const separator = (sectionID, rowID) => (
  106. <div
  107. key={`${sectionID}-${rowID}`}
  108. style={{
  109. backgroundColor: '#F5F5F9',
  110. height: 8,
  111. borderTop: '1px solid #ECECED',
  112. borderBottom: '1px solid #ECECED',
  113. }}
  114. />
  115. );
  116. let index = data.length - 1;
  117. const row = (rowData, sectionID, rowID) => {
  118. if (index < 0) {
  119. index = data.length - 1;
  120. }
  121. const obj = data[index--];
  122. return (
  123. <div
  124. key={rowID}
  125. style={{
  126. padding: '0 15px',
  127. backgroundColor: 'white',
  128. }}
  129. >
  130. <div style={{ height: '50px', lineHeight: '50px', color: '#888', fontSize: '18px', borderBottom: '1px solid #ddd' }}>
  131. {obj.title}
  132. </div>
  133. <div style={{ display: '-webkit-box', display: 'flex', padding: '15px' }}>
  134. <img style={{ height: '63px', width: '63px', marginRight: '15px' }} src={obj.img} alt="" />
  135. <div style={{ display: 'inline-block' }}>
  136. <div style={{ marginBottom: '8px', color: '#000', fontSize: '16px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '250px' }}>{obj.des}-{rowData}</div>
  137. <div style={{ fontSize: '16px' }}><span style={{ fontSize: '30px', color: '#FF6E27' }}>{rowID}</span> 元/任务</div>
  138. </div>
  139. </div>
  140. </div>
  141. );
  142. };
  143. return (<div>
  144. <ListView
  145. ref={el => this.lv = el}
  146. dataSource={this.state.dataSource}
  147. renderFooter={() => (<div style={{ padding: 30, textAlign: 'center' }}>
  148. {this.state.isLoading ? 'Loading...' : 'Loaded'}
  149. </div>)}
  150. renderRow={row}
  151. renderSeparator={separator}
  152. useBodyScroll={false}
  153. style={{
  154. height: this.state.height,
  155. border: '1px solid #ddd',
  156. margin: '5px 0',
  157. }}
  158. pullToRefresh={<PullToRefresh
  159. refreshing={this.state.refreshing}
  160. onRefresh={this.onRefresh}
  161. />}
  162. onEndReached={this.onEndReached}
  163. pageSize={5}
  164. />
  165. </div>);
  166. }
  167. }
  168. export default app

【花般绽放】balibali的更多相关文章

  1. NOI2019游记 —— 夏花般绚烂,繁星般璀璨

    NOI 2019 游记 夏花般绚烂,繁星般璀璨 打算写成两个形式 Dairy Day -1 早早就到gzez集训了20几天,对整体的环境熟悉很多 在gzez看了场LNR Day 2 然后回到宾馆搞了个 ...

  2. Oozie分布式任务的工作流——邮件篇

    在大数据的当下,各种spark和hadoop的框架层出不穷.各种高端的计算框架,分布式任务如乱花般迷眼.你是否有这种困惑!--有了许多的分布式任务,但是每天需要固定时间跑任务,自己写个调度,既不稳定, ...

  3. HoloLens shell overview(Translation)

    HoloLens shell 概述 使用HoloLens时,shell是由你周围的世界和来自系统的全息图构成.我们可以称这个空间叫做混合现实(mixed world). 此shell由在你的世界里能让 ...

  4. 服务发现:Zookeeper vs etcd vs Consul

    [编者的话]本文对比了Zookeeper.etcd和Consul三种服务发现工具,探讨了最佳的服务发现解决方案,仅供参考. 如果使用预定义的端口,服务越多,发生冲突的可能性越大,毕竟,不可能有两个服务 ...

  5. 从零開始制作H5应用(4)——V4.0,增加文字并给文字加特效

    之前,我们分三次完毕了我们第一个H5应用的三个迭代版本号: V1.0--简单页面滑动切换 V2.0--多页切换,透明过渡及交互指示 V3.0--加入loading,music及自己主动切换 这已经是一 ...

  6. Zookeeper vs etcd vs Consul

    Zookeeper vs etcd vs Consul [编者的话]本文对比了Zookeeper.etcd和Consul三种服务发现工具,探讨了最佳的服务发现解决方案,仅供参考. 如果使用预定义的端口 ...

  7. [P4994]终于结束的起点 (递推)

    终于结束的起点 终于写下句点 终于我们告别 终于我们又回到原点 …… 一个个 OIer 的竞赛生涯总是从一场 NOIp 开始,大多也在一场 NOIp 中结束,好似一次次轮回在不断上演. 如果这次 NO ...

  8. Docker容器学习梳理 - 基础知识(2)

    之前已经总结了Docker容器学习梳理--基础知识(1),但是不够详细,下面再完整补充下Docker学习的一些基础. Docker是个什么东西 Docker是一个程序运行.测试.交付的开放平台,Doc ...

  9. 服务发现:Zookeeper vs etcd vs Consul 参考自http://dockone.io/article/667

    服务发现:Zookeeper vs etcd vs Consul [编者的话]本文对比了Zookeeper.etcd和Consul三种服务发现工具,探讨了最佳的服务发现解决方案,仅供参考. 如果使用预 ...

随机推荐

  1. 如何将Map键值的下划线转为驼峰

    本文不再更新,可能存在内容过时的情况,实时更新请移步我的新博客:如何将Map键值的下划线转为驼峰: 例,将HashMap实例extMap键值下划线转为驼峰: 代码: HashMap<String ...

  2. 推荐5款超实用的.NET性能分析工具

    虽然.NET框架号称永远不会发生内存泄漏,原因是引入了内存回收机制.但在实际应用中,往往我们分配了对象但没有释放指向该对象的引用,导致对象永远无法释放.最常见的情况就是给对象添加了事件处理函数,但当不 ...

  3. 【python之路45】tornado的用法 (三)

    参考:https://www.cnblogs.com/sunshuhai/articles/6253815.html 一.cookie用法补充 1.cookie的应用场景 浏览器端保存的键值对,每次访 ...

  4. C++标准输入问题

    1.读取数据量不定的输入数据 e.g. #include <iostream> using namespace std; void main() { ,val=; while(cin> ...

  5. 014-unittest扩展

    unittest扩展 1. unittest框架里面---verbosity设置这里的verbosity是一个选项,表示测试结果的信息复杂度,有三个值: 0 (静默模式): 你只能获得总的测试用例数和 ...

  6. Java程序员面试题收集(4)

    Java面试题和答案JAVA相关基础知识1.面向对象的特征有哪些方面      1.抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题 ...

  7. PHP搜索优化 sphinx 实战

    环境:win7 64 wamp 解压sphinx安装包后,简历如下结构.注意,conf目录是我的配置文件目录 在conf目录下,简历newdefend.conf文件,配置内容如下 # 配置数据源 so ...

  8. PHP拓展 - xhprof性能分析工具

    Windows安装 参考:https://www.cnblogs.com/buexplain/p/4821619.html dll文件下载:https://windows.php.net/downlo ...

  9. CSS的color属性并非只能用于文本显示

    虽然CSS并不是一种很复杂的技术,但就算你是一个使用CSS多年的高手,仍然会有很多CSS用法/属性/属性值你从来没使用过,甚至从来没听说过. 对于CSS的color属性,相信所有Web开发人员都使用过 ...

  10. 常用长度单位PX/EM/PT/百分比转换公式与对照表

    PX.PT.EM.ex和in等都是我们常用的长度单位,尤其在网页的字体大小中经常用到.但是你知道PX.PT和EM之间是如何进行准换的吗?这里icech为大家找到了一个px.pt.em和percent大 ...