转眼,从接触react到如今,有一年多的时间了. 从一开始cv,学习语法,到如今本身写功能组件,封装. 分享一些心得.java
react中组件的开始.先分析下这个react
//生命周期的接口
interface Component<P = {}, S = {}, SS = any> extends ComponentLifecycle<P, S, SS> { }
class Component<P, S> {
//构造函数
constructor(props: Readonly<P>);
constructor(props: P, context?: any);
//咱们更新组件的setState
setState<K extends keyof S>(
state: ((prevState: Readonly<S>, props: Readonly<P>) => (Pick<S, K> | S | null)) | (Pick<S, K> | S | null),
callback?: () => void
): void;
forceUpdate(callBack?: () => void): void;
//组件的逻辑
render(): ReactNode;
readonly props: Readonly<{ children?: ReactNode }> & Readonly<P>;
//state对象
state: Readonly<S>;
context: any;
//组件引用
refs: {
[key: string]: ReactInstance
};
}
复制代码
日常写组件,经常使用到的就4个es6
render
state
setState
refs
bash
有人会说,还有constructor
呢.antd
实际上,我这个几乎没用到.app
早期的react,常规应该是这样的:函数
state的定义,函数的定义,都在constructor里面. 如今依然看到许多人这样写.其实也没啥毛病.oop
但我以为react,JSX,es6不错的地方.都让js更像编译语言,而不是脚本语言. 说直接点.很是像java之类的语言学习
做为一个写了几年java的人,我我的以为这样看起来舒服不少.哈哈.ui
这个标志也是继承,复写的意思.
其实无论什么语言, 开发设计都应该遵循六大设计原则:
单一职责原则(SRP):一个组件只作一件事
里氏替换原则(LSP): 继承
依赖倒转原则(DIP):多态
接口隔离原则(ISP):不要滥用接口(别继承没用的)
迪米特法则(LOD): 耦合
开闭原则(OCP):扩展性强(逻辑写好了别瞎JB改.要让人能扩展)
原理并不难,但真的要作好,仍是很须要技术的(废话).
单一职责原则
里氏替换原则
开闭原则
从我在交流群,还有看到的代码来讲,包括我本身. 这3个是最经常使用,却最容易被忽略.
不扯犊子了.
首先,想好一个需求(单一指责),尽可能不要太复杂.不要想太多.
1.间隔时间
2.当前展现内容(单个,或者多个)
3.开始,暂停
每次切换的回调
/**
* 定时切换
*/
class Test extends Component {
state = {
};
render() {
const { time, open, children } = this.props;
return (
<div>
</div>
);
}
}
Test.propTypes = {
// 间隔时间
time: PropTypes.number,
// 是否启动
open: PropTypes.bool,
};
export default Test;
复制代码
有人会问,为何展现内容的参数没定义.
这就涉及react中.children
这个参数了.
也就是咱们封装的组件下,包含的组件,就会在这个children
里面 debug看一下
因此展现内容,就不须要特地再去写一个参数了. 初始化
componentDidMount() {
this.notifyContent();
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (this.props.children !== prevProps.children) {
this.notifyContent();
}
}
notifyContent = () => {
const { children } = this.props;
const content = Array.isArray(children) ? children : [children];
this.setState({
content,
});
};
复制代码
这里就用setTimeout递归写了.
componentDidMount() {
this.loop();
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (this.props.open !== prevProps.open) {
this.loop();
}
}
loop = () => {
const { time = 1000, open = false } = this.props;
//若是没开就关闭
if (!open) {
return;
}
setTimeout(() => {
const { content, index } = this.state;
const newIndex = index + 1;
this.setState({
index: newIndex >= content.length ? 0 : newIndex
});
this.loop();
}, time);
};
复制代码
把loop改造一下,中间添加change方法
loop = () => {
const { time = 1000, open = false } = this.props;
if (!open) {
return;
}
setTimeout(() => {
const { content, index } = this.state;
this.change(index, content[index]);
const newIndex = index + 1;
this.setState({
index: newIndex >= content.length ? 0 : newIndex
});
this.loop();
}, time);
};
change = (index, content) => {
const { onChange, change } = this.props;
if (onChange) { //antd的form表单,默认会设置.
onChange(index, content);
}
if (change) {//因此通常写2个.
change(index, content);
}
};
复制代码
getItem = (index) => {
const { wrapper } = this.props;
const item = this.state.content[index];
if (wrapper) {
return wrapper(item, index);
}
return item;
};
复制代码
import React, { Component } from 'react';
import PropTypes from 'prop-types';
/**
* 定时切换
*/
class Test extends Component {
state = {
index: 0,
content: [],
};
componentDidMount() {
this.notifyContent();
this.loop();
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (this.props.open !== prevProps.open) {
this.loop();
}
if (this.props.children !== prevProps.children) {
this.notifyContent();
}
}
//更新,保存主内容引用
notifyContent = () => {
const { children } = this.props;
const content = Array.isArray(children) ? children : [children];
this.setState({
content,
});
};
// 定时循环
loop = () => {
const { time = 1000, open = false } = this.props;
if (!open) {
return;
}
setTimeout(() => {
const { content, index } = this.state;
this.change(index, content[index]);
const newIndex = index + 1;
this.setState({
index: newIndex >= content.length ? 0 : newIndex
});
this.loop();
}, time);
};
// 改变回调
change = (index, content) => {
const { onChange, change } = this.props;
if (onChange) { //antd的form表单,默认会设置.
onChange(index, content);
}
if (change) {//因此通常写2个.
change(index, content);
}
};
// 获取展现内容
getItem = (index) => {
const { wrapper } = this.props;
const item = this.state.content[index];
if (wrapper) {
return wrapper(item, index);
}
return item;
};
render() {
const { index } = this.state;
return (
<div>
{this.getItem(index)}
</div>
);
}
}
Test.propTypes = {
time: PropTypes.number,
open: PropTypes.bool,
wrapper: PropTypes.func,
change: PropTypes.func,
};
export default Test;
复制代码
<Test
open={true}
time={5000}
change={(i, item) => {
console.log(i, item);
}}>
<p>1</p>
<p>2</p>
<p>3</p>
</Test>
复制代码
是否是很简单.
propTypes是个好东西,必定要用 (若是你想让的你代码好维护的话)
效果就不贴了,作gif有点费事,有兴趣直接复制跑一下就完了.
欢迎你们点赞,留言交流