1.7 自定义组件

本文介绍了如何在React中实现Icon组件,包括点击事件和样式定制,以及Button、Input组件的使用,如类型设置、图标显示和输入验证。同时展示了Table组件的用法,包括列定义和数据源渲染。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 实现Icon

// icon组件的使用
  <Icon onClick={() => {
          alert('hello icon')
        }} name='jiadian-dianfanguo' style={{color:'red'}}/>
// icon组件
import React,{Component} from 'react'
import PropTypes from 'prop-types'
import '../../font-demo/iconfont.css' // 下载的图标库

class Icon extends Component{
	static propTypes = {
		name: PropTypes.string
	}

	static defaultProps = {
		name: 'aaa'
	}

	render() {
		const {
			name,
			...rest
		} = this.props
		return (
			<span {...rest} className={`icon iconfont icon-${name}`}></span>
		)
	}
}


export default Icon

2. 实现Button

// button 组件的使用
<Button onClick={() => {
					alert('hello button')
				}} type='primary' icon='jiadian-dianfanguo'>提交</Button>
//Button 
import React,{Component} from 'react'
import PropTypes from 'prop-types'
import Icon from '../Icon'
import './index.scss'
class Button extends Component{
	static propTypes = {
		icon: PropTypes.string,
		type: PropTypes.string
	}

	static defaultProps = {
		icon: 'dianpu',
		type: 'primary'
	}

	render() {
		const {
			icon,
			children,
			type,
			...rest
		} = this.props
		return (
			<button {...rest} className={`react-ui__btn--${type}`}>
				<Icon name={icon}/>
				{children}
			</button>
		)
	}
}


export default Button

3. 实现Input

// Input 组件的使用
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Input from './react-ui/Input/index1'

class  App extends React.Component{
	constructor(props) {
		super(props);
		this.state ={
			value: 'a'
		}
	}
	value = '1'

	render() {
		return (
			<div>
				<Input size='large'/>
				<br/>
				<Input size='middle' prefix='dianpu'/>
				<br/>
				<Input size='small'
				       value={this.state.value}
				       onChange={(e) => {
									this.setState({
										value: e.target.value
									})
				}}
				/>
				<Input
					rule={/\d/}
					message="只允许输入数字"
					size='small' defalutValue={this.value} onChange={(e) => {
					this.value = e.target.value
				}}/>
			</div>
		);
	}
}





export default App;
// Input 组件
import React,{Component} from 'react'
import classNames from 'classnames'
import PropTypes from 'prop-types'
import Icon from '../Icon'
import './index.scss'
class Input extends Component{
	constructor(props){
		super(props)
		this.state = {
			focus: false,
			innerValue: ''
		}
	}
	static propTypes = {
		value: PropTypes.string,
		onChange: PropTypes.func,
		size:PropTypes.string,
	}

	static defaultProps = {
		size: 'middle',
		onChange: () => {}
	}

	get isControl(){
		return 'value' in this.props
	}

	get value() {
		if(this.isControl){
			return this.props.value
		} else {
			return this.state.innerValue
		}
	}


	render() {
		const {
			focus
		} = this.state
		const {
			icon,
			children,
			size,
			prefix,
			suffix,
			onChange,
			rule= new RegExp(),
			message,
			...rest

		} = this.props
		let cls = classNames({
			input: true,
			focus,
			[`size-${size}`]: true,
			'react-ui__input': true
		})
		return (
			<div>
			<div className={cls}>
				{prefix && <Icon name={prefix}/>}
				<input
					value={this.value}

					onFocus={e => {
						this.setState({focus: true
						})
					}}
					onBlur={e => {
						this.setState({focus: false
						})
					}}
					onChange={(e) => {
						if(!this.isControl){
							this.setState({
								innerValue: e.target.value
							})
						}
						this.props.onChange(e)
					}}
				/>
				{suffix && <Icon name={suffix}/>}


			</div>
				<p>
					{!rule.test(this.value) && message}
				</p>
			</div>
		)
	}

	componentDidMount() {
		this.setState({
			innerValue: this.props.defaultValue
		})
	}

}


export default Input

// 受控
// 非受控
// Input 组件样式
$primaryColor: blue;
$warningColor: yellow

.react-ui__input{
  border: 1px solid #d2d2d2;
  display: inline-block;
  input{
    outline: none;
    border: none;
  }
  &.focus{
    border-color: blue;
  }

  &.size-large input{
    line-height: 40px;
    font-size: 18px;
  }
  &.size-small input{
    line-height: 20px;
    font-size: 14px;
  }
  &.middle input{
    font-size: 12px;
    line-height: 30px;
  }
  &--primary{
    //background: $primaryColor;
    color: #fff;
    background-color: #1890ff;
    border-color: #1890ff;
    text-shadow: 0 -1px 0 rgba(0,0,0,0.12);
  }
  &--warning{
    background: $warningColor;
  }
}

4. 实现Table

// Table的应用
import React from 'react';
import './App.css';
import Table from './react-ui/Table/index1'

let dataSource=[
	{
		name:'ryan',age:'30',sex:'man',
	},
	{
		name:'ryan2',age:'31',sex:'man',
	},
	{
		name:'ryan3',age:'32',sex:'man',
	}
]

class  App extends React.Component{

	render() {
		return (
			<div>
				<Table
					columns={[
						{title: '姓名', dataIndex:"name",key: 'name', render(text, item, index){
							return <div><a href='#'>{text} ? {item.age} + {index}</a></div>
						}},
						{title: '年龄', dataIndex:"age",key: 'age'},
						{title: '性别', dataIndex:"sex",key: 'sex'},
					]}
					dataSource={dataSource}

				/>
			</div>
		);
	}
}
export default App;
// Table组件内部实现
import React from 'react';
import PropTypes from 'prop-types';
import './index.scss';

class ColumnItem extends React.Component {
    render() {
        const {
            render = () => '占位符',
            title
        } = this.props.item;

        return(
            <th>{title}</th>
        )
    }
}
class Columns extends React.Component {
    render() {
        const {
            columns
        } = this.props;
        return(
            <thead>
                <tr>
                    {columns.map(item => <ColumnItem item={item} key={item.key}/>)}
                </tr>
            </thead>
        )
    }
}

class DataSourceItem extends React.Component {
    render() {
        const {
            columns,
            dataItem,
            index,
        } = this.props;
        const tds = columns.map((item) => <td key={item.dataIndex}>{item.render ? item.render(dataItem[item.dataIndex],dataItem,index) : dataItem[item.dataIndex]}</td>)
        return(
            <tr>
               {tds}
            </tr>
        )
    }
}
class DataSource extends React.Component {
    render() {
        const {
            dataSource,
            columns
        } = this.props;
        let trs = dataSource.map((item,index) => <DataSourceItem dataItem={item} index={index} columns={columns} key={item.name}/>);
        return(
            <tbody>
                { trs }
            </tbody>
        )
    }
}

class Table extends React.Component {
    static propTypes = {
        columns:PropTypes.array,
        dataSource: PropTypes.array
    }
    static defaultProps = {
        columns: [],
        dataSource: []
    }
    render() {
        const {
            columns,
            dataSource,
            ...rest
        } = this.props;
        return(
            <div>
                <table border='1'>
                <Columns columns={columns} />
                <DataSource dataSource={dataSource} columns={columns}/>
            </table>
            </div>
        )
    }
}

export default Table;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_陌默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值