react组件设计原则_React 如何封装一个简单的组件

前言

转眼,从接触react到现在,有一年多的时间了.

从一开始cv,学习语法,到现在自己写功能组件,封装.

分享一些心得.

1. Component

react中组件的开始.先分析下这个

//生命周期的接口

interface Component

extends ComponentLifecycle

{ }

class Component

{

//构造函数

constructor(props: Readonly

);

constructor(props: P, context?: any);

//我们更新组件的setState

setState(

state: ((prevState: Readonly, props: Readonly

) => (Pick | S | null)) | (Pick | S | null),

callback?: () => void

): void;

forceUpdate(callBack?: () => void): void;

//组件的逻辑

render(): ReactNode;

readonly props: Readonly & Readonly

;

//state对象

state: Readonly;

context: any;

//组件引用

refs: {

[key: string]: ReactInstance

};

}

复制代码

平常写组件,常用到的就4个

render state setState refs

有人会说,还有constructor呢.

实际上,我这个几乎没用到.

constructor

早期的react,常规应该是这样的:

state的定义,函数的定义,都在constructor里面.

现在依然看到许多人这样写.其实也没啥毛病.

但我觉得react,JSX,es6不错的地方.都让js更像编译语言,而不是脚本语言.

说直接点.非常像java之类的语言

作为一个写了几年java的人,我个人觉得这样看起来舒服很多.哈哈.

这个标志也是继承,复写的意思.

正题:

其实不管什么语言,

开发设计都应该遵循六大设计原则:

单一职责原则(SRP):一个组件只做一件事

里氏替换原则(LSP): 继承

依赖倒转原则(DIP):多态

接口隔离原则(ISP):不要滥用接口(别继承没用的)

迪米特法则(LOD): 耦合

开闭原则(OCP):扩展性强(逻辑写好了别瞎JB改.要让人能扩展)

原理并不难,但真的要做好,还是很需要技术的(废话).

最实用的:

单一职责原则 里氏替换原则 开闭原则

从我在交流群,还有看到的代码来说,包括我自己.

这3个是最常用,却最容易被忽略.

不扯犊子了.

实例.写一个定时的内容切换

首先,想好一个需求(单一指责),尽量不要太复杂.不要想太多.

一.分析需求.定义参数:

参数:

1.间隔时间

2.当前展示内容(单个,或者多个)

3.开始,暂停

回调:

每次切换的回调

定义:

/**

* 定时切换

*/

class Test extends Component {

state = {

};

render() {

const { time, open, children } = this.props;

return (

);

}

}

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 (

{this.getItem(index)}

);

}

}

Test.propTypes = {

time: PropTypes.number,

open: PropTypes.bool,

wrapper: PropTypes.func,

change: PropTypes.func,

};

export default Test;

复制代码

使用

open={true}

time={5000}

change={(i, item) => {

console.log(i, item);

}}>

1

2

3

复制代码

结语

是不是很简单.

propTypes是个好东西,一定要用 (如果你想让的你代码好维护的话)

效果就不贴了,做gif有点费事,有兴趣直接复制跑一下就完了.

欢迎大家点赞,留言交流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值