1.HOC
1.1HOC 基本使用
简介:HOC是一个函数,接受一个组件,返回一个新组件
// HocPage.js
import React, { Component } from 'react'
// 定义一个Hoc函数
const foo = Com =>props=>{
return (
<div className="border">
<Com {...props}/>
<div>
)
}
function child(props){
return <div> child:{props.name}</div>
}
const Foo = foo(child)
export default class HocPage extents Component {
render(){
return (
<div>
<h3>HocPage</H3>
<Foo name="msg"/>
</div>
)
}
}
1.2 HOC 链式调用 (因为其原理:入参和返回始终是一个组件,所以可以无限链式调用,最终返回的还是一个组件)
import React, { Component } from 'react'
// hoc:是一个函数,接受一个组件,返回另一个组件
const foo = Cmp => props => {
return (
<div className='border'>
<Cmp {...props} />
</div>
)
}
const foo2 = Cmp => props => {
return (
<div className="hotpinkBorder">
<Cmp {...props} />
</div>
)
}
function Child(props) {
return <div>Child {props.name}</div>
}
const Foo = foo2(foo(foo(Child)));
export default class HocPage extends Component {
render() {
return (
<div>
<h3>hocPage</h3>
<Foo name="msg"></Foo>
</div>
)
}
}
1.3 使用装饰器
- 1.3.1 安装插件
npm install react-app-rewired customize-cra --save-dev
npm install -D @babel/plugin-proposal-decorators
- 1.3.2 增加配置文件
// config-overrides.js
const { addDecoratorsLegacy, override } = require("customize-cra");
module.exports = override(
addDecoratorsLegacy()
)
- 1.3.3 修改package.json
/* package.json */
"scripts": {
- "start": "react-scripts start",
+ "start": "react-app-rewired start",
- "build": "react-scripts build",
+ "build": "react-app-rewired build",
- "test": "react-scripts test --env=jsdom",
+ "test": "react-app-rewired test --env=jsdom",
}
+1.3.4 使用
import React, { Component } from 'react'
// hoc:是一个函数,接受一个组件,返回另一个组件
const foo = Cmp => props => {
return (
<div className='border'>
<Cmp {...props} />
</div>
)
}
const foo2 = Cmp => props => {
return (
<div className="hotpinkBorder">
<Cmp {...props} />
</div>
)
}
// 从下往上
@foo2
@foo
@foo
class Child extends Component {
render() {
return <div>Child</div>;
}
}
export default class HocPage extends Component {
render() {
return (
<div>
<h3>hocPage</h3>
{/* <Foo name="msg"></Foo> */}
<Child name="msg" />
</div>
)
}
}
注意:不要在render方法中使用HOC
2.设计表单组件
2.1 antd 表单基本使用
import React, { Component } from 'react'
import { Form, Input, Button } from 'antd'
export default class FromPage extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
password: ""
}
}
submit() {
console.log("submit", this.state)
}
render() {
const { name, password } = this.state;
return (
<div>
<h3>FromPage</h3>
<Form>
<Form.Item label="姓名">
<Input placeholder="请输入姓名"
value={name}
onChange={e => {
this.setState({ name: e.target.value })
}}>
</Input>
</Form.Item>
<Form.Item label="密码">
<Input type='password' placeholder="请输入密码"
value={password}
onChange={e => {
this.setState({ password: e.target.value })
}}>
</Input>
</Form.Item>
<Button type='primary' onClick={this.submit.bind(this)}>提交</Button>
</Form>
</div>
)
}
}
2.2 自己实现From组件
2.2.1 创建一个from组件的HOC
// FromCreate.js
import React, { Component } from 'react'
export default function kFromCreate(Cmp) {
return class extends Component {
constructor(props) {
super(props);
this.state = {};
this.options = {};
}
handleChange = e => {
let { name, value } = e.target
this.setState({ [name]: value })
};
getFieldDecorator = (field, option) => {
this.options[field] = option;
return InputCmp =>
React.cloneElement(InputCmp, {
name: field,
value: this.state[field] || "",
onChange: this.handleChange
})
}
getFieldsValue = () => {
return { ...this.state }
}
getFiledValue = (field) => {
return this.state[field]
}
validateFields = callback => {
let errors = {};
const state = { ...this.state };
console.log(state, this.options)
for (const key in this.options) {
if (state[key] === undefined) {
errors[key] = "error"
}
}
if (JSON.stringify(errors) === "{}") {
callback(undefined, state)
} else {
callback(errors, state);
}
}
render() {
return (
<div className='border'>
<Cmp
{...this.props}
getFieldDecorator={this.getFieldDecorator}
getFieldsValue={this.getFieldsValue}
getFiledValue={this.getFiledValue}
validateFields={this.validateFields} />
</div>
)
}
}
}
2.2.2 创建From组件
// MyFromPage.js
import React, { Component } from 'react'
import MyFromCreate from './FromCreate'
// 校验规则
const nameRules = { required: true, message: "请输入姓名" }
const passwordRules = { required: true, message: "请输入密码" }
export default MyFromCreate(
class MyFromPage extends Component {
submit = () => {
const { getFieldsValue, getFiledValue, validateFields } = this.props
console.log(getFieldsValue(), getFiledValue('name'))
validateFields((err, values) => {
if (err) {
console.error(err)
} else {
console.log(values)
}
})
}
render() {
console.log("props", this.props)
const { getFieldDecorator } = this.props
return (
<div>
<h3>MyFromPage</h3>
{getFieldDecorator('name', { rules: [nameRules] })(
<input type="text" placeholder="请输入用户名"></input>
)}
{
getFieldDecorator('password', { rules: [passwordRules] })(
<input type="password" placeholder="请输入密码"></input>
)
}
<button onClick={this.submit}>提交</button>
</div>
)
}
}
)
3.设计弹窗组件
3.1 封转dialog样式
// dialog.js
import React, { Component } from 'react'
import { createPortal } from 'react-dom'
export default class Dialog extends Component {
constructor(props) {
super(props)
this.node = document.createElement('div')
this.node.classList.add("sss")
}
componentDidMount() {
document.body.appendChild(this.node)
}
componentWillUnmount() {
document.body.removeChild(this.node)
}
render() {
const { hideDialog, children } = this.props
return createPortal(
<div>
{children}
{typeof hideDialog == "function" && (
<button onClick={hideDialog}>关闭窗口</button>
)}
</div>, this.node)
}
}
3.2 使用dialog
// DialogPage.js
import React, { Component } from 'react'
import Diallog from './Diallog'
export default class DialogPage extends Component {
constructor(props) {
super(props)
this.state = {
isShowDialog: false
}
}
render() {
const { isShowDialog } = this.state;
return (
<div>
<h3>DialogPage</h3>
<button onClick={() => this.setState({
isShowDialog: !isShowDialog
})}>
toggle
</button>
{isShowDialog && <Diallog children="hello" hideDialog={() => this.setState({
isShowDialog: false
})} />}
</div>
)
}
}
网友评论