├── README.md ├── .gitignore ├── react-learn ├── src │ ├── components │ │ └── common │ │ │ ├── ThreeLayout │ │ │ ├── README.md │ │ │ ├── index.css │ │ │ └── index.js │ │ │ ├── Banner │ │ │ ├── img │ │ │ │ ├── 1.jpg │ │ │ │ ├── 2.webp │ │ │ │ ├── 3.jpg │ │ │ │ ├── 4.jpg │ │ │ │ └── 5.webp │ │ │ ├── index.css │ │ │ ├── SwitchDot │ │ │ │ ├── index.css │ │ │ │ └── index.js │ │ │ ├── Test.js │ │ │ ├── SwitchArrow │ │ │ │ ├── index.css │ │ │ │ └── index.js │ │ │ ├── ImgContainer │ │ │ │ └── index.js │ │ │ └── index.js │ │ │ ├── Modal │ │ │ ├── index.css │ │ │ └── index.js │ │ │ ├── Select │ │ │ ├── README.md │ │ │ ├── Test.js │ │ │ └── index.js │ │ │ ├── RadioBoxGroup │ │ │ ├── README.md │ │ │ ├── Test.js │ │ │ └── index.js │ │ │ ├── CheckBoxGroup │ │ │ ├── README.md │ │ │ ├── Test.js │ │ │ └── index.js │ │ │ ├── Pager │ │ │ ├── index.css │ │ │ └── index.js │ │ │ ├── hoc │ │ │ └── withDataGroup.js │ │ │ └── ErrorBound │ │ │ └── index.js │ ├── App.js │ ├── index.js │ ├── utils │ │ └── commonTypes.js │ └── services │ │ └── student.js ├── public │ ├── favicon.ico │ └── index.html ├── .gitignore ├── package.json └── README.md ├── 旧版生命周期.pptx ├── 新版生命周期 .pptx └── 属性验证.md /README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | upload 4 | build 5 | ~* -------------------------------------------------------------------------------- /react-learn/src/components/common/ThreeLayout/README.md: -------------------------------------------------------------------------------- 1 | # 说明文件 2 | 3 | -------------------------------------------------------------------------------- /旧版生命周期.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-React/HEAD/旧版生命周期.pptx -------------------------------------------------------------------------------- /新版生命周期 .pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-React/HEAD/新版生命周期 .pptx -------------------------------------------------------------------------------- /react-learn/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-React/HEAD/react-learn/public/favicon.ico -------------------------------------------------------------------------------- /react-learn/src/components/common/Banner/img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-React/HEAD/react-learn/src/components/common/Banner/img/1.jpg -------------------------------------------------------------------------------- /react-learn/src/components/common/Banner/img/2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-React/HEAD/react-learn/src/components/common/Banner/img/2.webp -------------------------------------------------------------------------------- /react-learn/src/components/common/Banner/img/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-React/HEAD/react-learn/src/components/common/Banner/img/3.jpg -------------------------------------------------------------------------------- /react-learn/src/components/common/Banner/img/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-React/HEAD/react-learn/src/components/common/Banner/img/4.jpg -------------------------------------------------------------------------------- /react-learn/src/components/common/Banner/img/5.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuYi-Edu/DuYi-React/HEAD/react-learn/src/components/common/Banner/img/5.webp -------------------------------------------------------------------------------- /react-learn/src/components/common/Banner/index.css: -------------------------------------------------------------------------------- 1 | .banner-container{ 2 | position: relative; 3 | border: 2px solid; 4 | overflow: hidden; 5 | } -------------------------------------------------------------------------------- /react-learn/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export default function App() { 4 | return ( 5 |
6 |
7 | ) 8 | } 9 | -------------------------------------------------------------------------------- /react-learn/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from "./App" 4 | 5 | ReactDOM.render(, document.getElementById('root')); -------------------------------------------------------------------------------- /react-learn/src/components/common/Modal/index.css: -------------------------------------------------------------------------------- 1 | .modal { 2 | position: fixed; 3 | width: 100%; 4 | height: 100%; 5 | left: 0; 6 | top: 0; 7 | } 8 | 9 | .modal-center { 10 | position: absolute; 11 | left: 50%; 12 | top: 50%; 13 | transform: translate(-50%, -50%); 14 | } -------------------------------------------------------------------------------- /react-learn/src/components/common/ThreeLayout/index.css: -------------------------------------------------------------------------------- 1 | .three-layout { 2 | display: flex; 3 | } 4 | 5 | .three-layout .aside-left { 6 | order: 1; 7 | } 8 | 9 | .three-layout .main{ 10 | order: 2; 11 | flex: 1 1 auto; 12 | } 13 | 14 | .three-layout .aside-right{ 15 | order: 3; 16 | } -------------------------------------------------------------------------------- /react-learn/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React App 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /react-learn/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /react-learn/src/components/common/Select/README.md: -------------------------------------------------------------------------------- 1 | **属性** 2 | 3 | 1. datas:一个数组,数组每一项是一个对象,对应一个多选框 4 | 1. 对象具有value和text属性 5 | 2. value:多选框的值 6 | 3. text:多选框的文本 7 | 8 | 例如: 9 | 10 | ```js 11 | datas = [ 12 | {value:"football", text:"足球"}, 13 | {value:"basketball", text:"篮球"}, 14 | {value:"movie", text:"电影"}, 15 | ] 16 | ``` 17 | 18 | 2. name:每一个多选框的name属性值 19 | 3. value: 当前选中的value值 20 | 4. onChange:当选中项发生改变时的事件 -------------------------------------------------------------------------------- /react-learn/src/components/common/RadioBoxGroup/README.md: -------------------------------------------------------------------------------- 1 | **属性** 2 | 3 | 1. datas:一个数组,数组每一项是一个对象,对应一个多选框 4 | 1. 对象具有value和text属性 5 | 2. value:多选框的值 6 | 3. text:多选框的文本 7 | 8 | 例如: 9 | 10 | ```js 11 | datas = [ 12 | {value:"football", text:"足球"}, 13 | {value:"basketball", text:"篮球"}, 14 | {value:"movie", text:"电影"}, 15 | ] 16 | ``` 17 | 18 | 2. name:每一个多选框的name属性值 19 | 3. value: 当前选中的value值 20 | 4. onChange:当选中项发生改变时的事件 -------------------------------------------------------------------------------- /react-learn/src/components/common/CheckBoxGroup/README.md: -------------------------------------------------------------------------------- 1 | **属性** 2 | 3 | 1. datas:一个数组,数组每一项是一个对象,对应一个多选框 4 | 1. 对象具有value和text属性 5 | 2. value:多选框的值 6 | 3. text:多选框的文本 7 | 8 | 例如: 9 | 10 | ```js 11 | datas = [ 12 | {value:"football", text:"足球"}, 13 | {value:"basketball", text:"篮球"}, 14 | {value:"movie", text:"电影"}, 15 | ] 16 | ``` 17 | 18 | 2. name:每一个多选框的name属性值 19 | 3. chooseDatas: 数组,表示当前选中的value值 20 | 4. onChange:当选中项发生改变时的事件 -------------------------------------------------------------------------------- /react-learn/src/components/common/Pager/index.css: -------------------------------------------------------------------------------- 1 | .item { 2 | display: inline-block; 3 | padding: 6px 10px; 4 | border: 1px solid #ccc; 5 | margin: 2px; 6 | color: rgb(23, 96, 121); 7 | cursor: pointer; 8 | } 9 | 10 | .item.disabled{ 11 | color: #ccc; 12 | cursor: not-allowed; 13 | } 14 | 15 | .current{ 16 | margin-left: 10px; 17 | } 18 | 19 | .active{ 20 | border: none; 21 | color: #f40; 22 | cursor: auto; 23 | } -------------------------------------------------------------------------------- /react-learn/src/utils/commonTypes.js: -------------------------------------------------------------------------------- 1 | import PropTypes from "prop-types" 2 | 3 | export default { 4 | children: PropTypes.node, 5 | groupDatas: PropTypes.arrayOf(PropTypes.shape({ 6 | value: PropTypes.string.isRequired, 7 | text: PropTypes.string.isRequired 8 | })), //多选框组、单选框组、下拉列表的数据源 9 | chooseDatas: PropTypes.arrayOf(PropTypes.string), 10 | singleData: PropTypes.shape({ 11 | value: PropTypes.string.isRequired, 12 | text: PropTypes.string.isRequired 13 | }) 14 | } -------------------------------------------------------------------------------- /react-learn/src/services/student.js: -------------------------------------------------------------------------------- 1 | const appkey = "demo13_1545210570249"; 2 | 3 | /** 4 | * 获取所有学生 5 | */ 6 | export async function getAllStudents() { 7 | return await fetch("/api/student/findAll?appkey=" + appkey) 8 | .then(resp => resp.json()).then(resp => resp.data); 9 | } 10 | 11 | export async function getStudents(page = 1, limit = 10) { 12 | return await fetch(`/api/student/findByPage?appkey=${appkey}&page=${page}&size=${limit}`) 13 | .then(resp => resp.json()).then(resp => resp.data); 14 | } -------------------------------------------------------------------------------- /react-learn/src/components/common/Banner/SwitchDot/index.css: -------------------------------------------------------------------------------- 1 | .dots{ 2 | position: absolute; 3 | padding: 2px 4px; 4 | background: rgba(255,255,255,.3); 5 | border-radius: 8px; 6 | left: 50%; 7 | bottom: 10px; 8 | transform: translateX(-50%); 9 | display: flex; 10 | } 11 | 12 | .dots span{ 13 | width: 8px; 14 | height: 8px; 15 | background: #fff; 16 | border-radius: 50%; 17 | margin: 3px; 18 | cursor: pointer; 19 | } 20 | 21 | .dots span.active{ 22 | background: #f40; 23 | } -------------------------------------------------------------------------------- /react-learn/src/components/common/Banner/Test.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import Banner from "./index" 3 | import src1 from "./img/1.jpg" 4 | import src2 from "./img/2.webp" 5 | import src3 from "./img/3.jpg" 6 | import src4 from "./img/4.jpg" 7 | import src5 from "./img/5.webp" 8 | export default class Test extends Component { 9 | render() { 10 | return ( 11 |
12 | 15 |
16 | ) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /react-learn/src/components/common/hoc/withDataGroup.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import types from "../../../utils/commonTypes" 3 | //实现根据数据渲染出的一组表单组件 4 | 5 | export default function withDataGroup(Comp) { 6 | return class DataGroupWrapper extends React.Component { 7 | static defaultProps = { 8 | datas: [] 9 | } 10 | 11 | static propTypes = { 12 | datas: types.groupDatas 13 | } 14 | 15 | render() { 16 | const comps = this.props.datas.map(it => ) 17 | return <> 18 | {comps} 19 | 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /react-learn/src/components/common/Banner/SwitchArrow/index.css: -------------------------------------------------------------------------------- 1 | .arrow{ 2 | display: none; 3 | } 4 | .banner-container:hover .arrow{ 5 | display: block; 6 | } 7 | .arrow span{ 8 | position: absolute; 9 | color: #fff; 10 | width: 20px; 11 | height: 30px; 12 | line-height: 30px; 13 | top: 50%; 14 | transform: translateY(-50%); 15 | background: rgba(0,0,0,.5); 16 | box-sizing: border-box; 17 | cursor: pointer; 18 | } 19 | 20 | .arrow span:hover{ 21 | background: rgba(0,0,0,.7); 22 | } 23 | 24 | .arrow .left{ 25 | left: 0; 26 | border-radius: 0 30px 30px 0; 27 | } 28 | 29 | .arrow .right{ 30 | right: 0; 31 | border-radius: 30px 0 0 30px; 32 | padding-left: 6px; 33 | } -------------------------------------------------------------------------------- /react-learn/src/components/common/ErrorBound/index.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react' 2 | 3 | export default class ErrorBound extends PureComponent { 4 | 5 | state = { 6 | hasError: false 7 | } 8 | 9 | static getDerivedStateFromError(error) { 10 | console.log("发生错误了"); 11 | return { 12 | hasError: true 13 | } 14 | } 15 | 16 | componentDidCatch(error, info) { 17 | console.log("记录错误信息"); 18 | } 19 | 20 | 21 | 22 | render() { 23 | // setTimeout(() => { 24 | // throw new Error("asfasdfasf"); 25 | // }, 1000); 26 | if (this.state.hasError) { 27 | return

出现错误了!

28 | } 29 | return this.props.children 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /react-learn/src/components/common/Modal/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import "./index.css" 3 | import types from "../../../utils/commonTypes" 4 | import PropTypes from "prop-types" 5 | 6 | Modal.defaultProps = { //默认属性 7 | bg: "rgba(0,0,0,.5)" 8 | }; 9 | 10 | Modal.propTypes = { 11 | children: types.children, 12 | bg: PropTypes.string, 13 | onClose: PropTypes.func 14 | } 15 | 16 | export default function Modal(props) { 17 | 18 | return ( 19 |
{ 20 | if (e.target.className === "modal") { 21 | props.onClose(); 22 | } 23 | }} className="modal" style={{ 24 | background: props.bg 25 | }}> 26 |
27 | {props.children} 28 |
29 |
30 | ) 31 | } 32 | -------------------------------------------------------------------------------- /react-learn/src/components/common/Banner/SwitchArrow/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import "./index.css"; 3 | import PropTypes from "prop-types"; 4 | export default class SwitchArrow extends Component { 5 | 6 | static propTypes = { 7 | onChange: PropTypes.func 8 | } 9 | 10 | render() { 11 | return ( 12 |
13 | { 14 | this.props.onChange && this.props.onChange("left"); 15 | }}> 16 | < 17 | 18 | { 19 | this.props.onChange && this.props.onChange("right"); 20 | }}> 21 | > 22 | 23 |
24 | ) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /react-learn/src/components/common/Banner/SwitchDot/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import PropTypes from "prop-types"; 3 | import "./index.css" 4 | 5 | export default class SwitchDot extends Component { 6 | 7 | static propTypes = { 8 | total: PropTypes.number.isRequired, 9 | curIndex: PropTypes.number.isRequired, //当前选中的下标 10 | onChange: PropTypes.func 11 | } 12 | 13 | render() { 14 | const spans = []; 15 | for (let i = 0; i < this.props.total; i++) { 16 | spans.push( { 19 | this.props.onChange && this.props.onChange(i) 20 | }} 21 | >); 22 | } 23 | return ( 24 |
25 | {spans} 26 |
27 | ) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /react-learn/src/components/common/Select/Test.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import Select from "./index" 3 | import { getAllStudents } from "../../../services/student" 4 | 5 | export default class Test extends Component { 6 | state = { 7 | datas: [], 8 | value: "" 9 | } 10 | 11 | async componentDidMount() { 12 | const stus = await getAllStudents(); 13 | this.setState({ 14 | datas: stus.map(it => ({ value: it.id.toString(), text: it.name })) 15 | }) 16 | } 17 | 18 | 19 | render() { 20 | return ( 21 |
22 | { 22 | this.props.onChange && this.props.onChange(this.props.info.value) 23 | }} 24 | /> 25 | {this.props.info.text} 26 | 27 | } 28 | } 29 | 30 | export default withDataGroup(Radio); 31 | -------------------------------------------------------------------------------- /react-learn/src/components/common/Select/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import types from "../../../utils/commonTypes" 3 | import PropTypes from "prop-types" 4 | import withDataGroup from "../hoc/withDataGroup"; 5 | 6 | class Option extends Component { 7 | static propTypes = { 8 | info: types.singleData 9 | } 10 | 11 | render() { 12 | return 15 | } 16 | } 17 | 18 | const OptGroup = withDataGroup(Option); 19 | 20 | export default class Select extends Component { 21 | static propTypes = { 22 | name: PropTypes.string.isRequired, 23 | value: PropTypes.string.isRequired, 24 | onChange: PropTypes.func 25 | } 26 | 27 | 28 | render() { 29 | return 36 | } 37 | } -------------------------------------------------------------------------------- /react-learn/src/components/common/ThreeLayout/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import "./index.css" 3 | import types from "../../../utils/commonTypes" 4 | import PropTypes from "prop-types" 5 | 6 | ThreeLayout.defaultProps = { 7 | leftWidth: 200, 8 | rightWidth: 200, 9 | minWidth: 800, 10 | gap: 0//间隙 11 | }; 12 | 13 | ThreeLayout.propTypes = { 14 | leftWidth: PropTypes.number, 15 | rightWidth: PropTypes.number, 16 | minWidth: PropTypes.number, 17 | gap: PropTypes.number, 18 | children: types.children, 19 | left: PropTypes.node, 20 | right: PropTypes.node 21 | } 22 | 23 | export default function ThreeLayout(props) { 24 | return ( 25 |
28 |
29 | {props.children} 30 |
31 |
35 | {props.left} 36 |
37 |
41 | {props.right} 42 |
43 |
44 | ) 45 | } 46 | -------------------------------------------------------------------------------- /react-learn/src/components/common/CheckBoxGroup/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import types from "../../../utils/commonTypes" 3 | import PropTypes from "prop-types" 4 | import withDataGroup from "../hoc/withDataGroup" 5 | class CheckBox extends Component { 6 | static propTypes = { 7 | name: PropTypes.string.isRequired, 8 | onChange: PropTypes.func, 9 | info: types.singleData.isRequired, 10 | chooseDatas: types.chooseDatas.isRequired 11 | } 12 | 13 | handleChange = e => { 14 | let newArr; 15 | if (e.target.checked) { 16 | newArr = [...this.props.chooseDatas, e.target.value]; 17 | } 18 | else { 19 | newArr = this.props.chooseDatas.filter(it => it !== e.target.value); 20 | } 21 | this.props.onChange && this.props.onChange(newArr); 22 | } 23 | 24 | render() { 25 | return (); 35 | } 36 | } 37 | 38 | /** 39 | * 一组多选框 40 | */ 41 | export default withDataGroup(CheckBox); 42 | -------------------------------------------------------------------------------- /react-learn/src/components/common/Banner/ImgContainer/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import PropTypes from "prop-types" 3 | 4 | export default class ImgContainer extends Component { 5 | 6 | static propTypes = { 7 | imgSrcs: PropTypes.arrayOf(PropTypes.string).isRequired, //图片路径的数组 8 | imgWidth: PropTypes.number.isRequired, //单张图片宽度 9 | imgHeight: PropTypes.number.isRequired, //单张图片高度 10 | duration: PropTypes.number.isRequired, //在多长时间内完成动画切换 11 | } 12 | 13 | containerRef = el => { 14 | this.div = el; 15 | } 16 | 17 | //计时器的间隔时间 18 | tick = 16 19 | 20 | timer = null;//计时器序号 21 | 22 | /** 23 | * 切换到第几张图片 24 | * 调用该函数,此组件会经过一段动画完成切换 25 | * @param {*} index 图片下标,从0开始 26 | */ 27 | switchTo(index) { 28 | //设置正确的index 29 | if (index < 0) { 30 | index = 0; 31 | } 32 | else if (index > this.props.imgSrcs.length - 1) { 33 | index = this.props.imgSrcs.length - 1; 34 | } 35 | //1. 根据index,计算div的最终的marginLeft 36 | const targetLeft = -index * this.props.imgWidth; 37 | //2. 得到当前的marginLeft 38 | let curLeft = parseFloat(window.getComputedStyle(this.div).marginLeft); 39 | //3. 计算运动的次数 40 | const times = Math.ceil(this.props.duration / this.tick); 41 | let curTimes = 0; //当前运动的次数 42 | //4. 计算每次运动的距离 43 | const totalDis = targetLeft - curLeft; //总距离 44 | const dis = totalDis / times; //每次运动的距离 45 | //先停止之前的动画 46 | clearInterval(this.timer); 47 | this.timer = setInterval(() => { 48 | curTimes++; 49 | curLeft += dis; 50 | this.div.style.marginLeft = curLeft + "px"; 51 | if (curTimes === times) { 52 | //停止运动 53 | this.div.style.marginLeft = targetLeft + "px"; 54 | clearInterval(this.timer); 55 | } 56 | }, this.tick) 57 | } 58 | 59 | render() { 60 | const imgs = this.props.imgSrcs.map((src, i) => ) 65 | return ( 66 |
72 | {imgs} 73 |
74 | ) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /react-learn/src/components/common/Pager/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import "./index.css" 3 | 4 | /** 5 | * 分页组件 6 | * 属性: 7 | * 1. current:初始页码 8 | * 2. total:总数据量 9 | * 3. limit:页容量,每页显示的数据量 10 | * 4. panelNumber:数字页码最多显示多少个 11 | * 5. onPageChange:当页码改变的事件 12 | */ 13 | export default function Pager(props) { 14 | const pageNumber = getPageNumber(props); //总页数 15 | if (pageNumber === 0) { 16 | return null; 17 | } 18 | const min = getMinNumber(props);//最小数字 19 | const max = getMaxNumber(min, pageNumber, props); //最大数字 20 | const numbers = []; 21 | for (let i = min; i <= max; i++) { 22 | numbers.push( { toPage(i, props) }} className={i === props.current ? "item active" : "item"}>{i}) 23 | } 24 | return ( 25 | <> 26 | { toPage(1, props) }} 28 | className={props.current === 1 ? "item disabled" : "item"} 29 | >首页 30 | { toPage(props.current - 1 < 1 ? 1 : props.current - 1, props) }} 32 | className={props.current === 1 ? "item disabled" : "item"} 33 | >上一页 34 | {/* 数字页码 */} 35 | {numbers} 36 | { toPage(props.current + 1 > pageNumber ? pageNumber : props.current + 1, props) }} 38 | className={props.current === pageNumber ? "item disabled" : "item"} 39 | >下一页 40 | { toPage(pageNumber, props) }} 42 | className={props.current === pageNumber ? "item disabled" : "item"} 43 | >尾页 44 | 45 | {props.current} 46 | / 47 | {pageNumber} 48 | 49 | ); 50 | } 51 | 52 | /** 53 | * 计算最小数字 54 | */ 55 | function getMinNumber(props) { 56 | var min = props.current - Math.floor(props.panelNumber / 2) 57 | if (min < 1) { 58 | min = 1; 59 | } 60 | return min; 61 | } 62 | 63 | /** 64 | * 计算最大数字 65 | * @param {*} min 66 | * @param {*} pageNumber 67 | */ 68 | function getMaxNumber(min, pageNumber, props) { 69 | var max = min + props.panelNumber - 1; 70 | if (max > pageNumber) { 71 | max = pageNumber; 72 | } 73 | return max; 74 | } 75 | 76 | /** 77 | * 跳转到某一页 78 | * @param {*} target 目标页码 79 | * @param {*} props 所有属性 80 | */ 81 | function toPage(target, props) { 82 | if (props.current === target) { 83 | return; //目标页码和当前页码相同 84 | } 85 | props.onPageChange && props.onPageChange(target); 86 | } 87 | 88 | 89 | /** 90 | * 计算总页数 91 | * @param {*} props 92 | */ 93 | function getPageNumber(props) { 94 | return Math.ceil(props.total / props.limit); 95 | } -------------------------------------------------------------------------------- /react-learn/README.md: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 2 | 3 | ## Available Scripts 4 | 5 | In the project directory, you can run: 6 | 7 | ### `npm start` 8 | 9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 11 | 12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console. 14 | 15 | ### `npm test` 16 | 17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 19 | 20 | ### `npm run build` 21 | 22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance. 24 | 25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed! 27 | 28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 29 | 30 | ### `npm run eject` 31 | 32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 33 | 34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 35 | 36 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 37 | 38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 39 | 40 | ## Learn More 41 | 42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 43 | 44 | To learn React, check out the [React documentation](https://reactjs.org/). 45 | 46 | ### Code Splitting 47 | 48 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting 49 | 50 | ### Analyzing the Bundle Size 51 | 52 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size 53 | 54 | ### Making a Progressive Web App 55 | 56 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app 57 | 58 | ### Advanced Configuration 59 | 60 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration 61 | 62 | ### Deployment 63 | 64 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment 65 | 66 | ### `npm run build` fails to minify 67 | 68 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify 69 | -------------------------------------------------------------------------------- /react-learn/src/components/common/Banner/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import "./index.css" 3 | import PropTypes from "prop-types"; 4 | import ImgContainer from "./ImgContainer" 5 | import SwitchArrow from "./SwitchArrow" 6 | import SwitchDot from './SwitchDot' 7 | 8 | export default class Banner extends Component { 9 | 10 | static defaultProps = { 11 | width: 520, 12 | height: 280, 13 | imgSrcs: [], 14 | autoDuration: 3000, 15 | duration: 500 16 | } 17 | 18 | static propTypes = { 19 | width: PropTypes.number.isRequired,//容器宽度 20 | height: PropTypes.number.isRequired, //容器高度 21 | imgSrcs: PropTypes.arrayOf(PropTypes.string).isRequired, //图片路径数组 22 | autoDuration: PropTypes.number.isRequired, //自动切换的间隔时间 23 | duration: PropTypes.number.isRequired,//完成一次切换需要的时间 24 | } 25 | 26 | timer = null; //自动切换的计时器 27 | 28 | autoSwitch() { 29 | clearInterval(this.timer); 30 | this.timer = setInterval(() => { 31 | var cur = this.state.curIndex; 32 | cur = (cur + 1) % this.props.imgSrcs.length; 33 | this.handleSwitch(cur); 34 | }, this.props.autoDuration) 35 | } 36 | 37 | componentWillUnmount() { 38 | clearInterval(this.timer); 39 | } 40 | 41 | 42 | componentDidMount() { 43 | this.autoSwitch(); 44 | } 45 | 46 | 47 | state = { 48 | curIndex: 0 //当前显示的第几张图片 49 | } 50 | 51 | imgContainerRef = el => { 52 | this.imgContainer = el; 53 | } 54 | 55 | handleArrowChange = type => { 56 | var cur = this.state.curIndex; 57 | if (type === "left") { 58 | cur--; 59 | if (cur < 0) { 60 | cur = this.props.imgSrcs.length - 1; 61 | } 62 | } 63 | else { 64 | cur++; 65 | if (cur > this.props.imgSrcs.length - 1) { 66 | cur = 0; 67 | } 68 | } 69 | this.handleSwitch(cur); 70 | } 71 | 72 | /** 73 | * 切换到 74 | */ 75 | handleSwitch = index => { 76 | this.setState({ 77 | curIndex: index 78 | }) 79 | //得到ImgContainer的组件对象 80 | this.imgContainer.switchTo(index); 81 | } 82 | 83 | render() { 84 | return ( 85 |
{ 92 | clearInterval(this.timer); 93 | }} 94 | onMouseLeave={()=>{ 95 | this.autoSwitch(); 96 | }} 97 | > 98 | 105 | 108 | 113 |
114 | ) 115 | } 116 | } 117 | --------------------------------------------------------------------------------