目錄
- 1,目標
- 2,實現
- 2.1,index.js
- 2.2,context.js
- 2.2,Form.Input
- 2.3,Form.Button
- 3,使用
1,目標
上篇文章說到,context
上下文一般用于第3方組件庫,因為使用場景是需要多個組件之間相互配合實現一整套的邏輯。(高內聚的思想)
所以利用上下文的特性簡單封裝一個表單,看看如何實現和使用。
在 element-ui 中 Form 表單組件之間的聯動,也是一個思想。它使用的 發布訂閱模式 來逐層傳遞數據。
2,實現
整體目錄:
src/components/Form
-- index.js
-- context.js // 存放上下文數據。
-- FormInput.js
-- FormButton.js
2.1,index.js
import React, { Component } from "react";
import PropTypes from "prop-types"; // 用于驗證 props 類型
import { Provider } from "./context";
import FormInput from "./FormInput";
import FormButton from "./FormButton";export default class Form extends Component {state = {formData: {},changeFormData: (name, value) => {this.setState({formData: {...this.state.formData,[name]: value,},});},submit: () => {this.props.onSubmit?.(this.state.formData);},};static propTypes = {onSubmit: PropTypes.func,};render() {return <Provider value={this.state}>{this.props.children}</Provider>;}
}// 賦值到 Form 組件上方便引用。
Form.Input = FormInput;
Form.Button = FormButton;
2.2,context.js
import React from "react";const ctx = React.createContext();
export const { Provider, Consumer } = ctx;
export default ctx;
2.2,Form.Input
注意 input.value
屬性,因為 this.context.formData[this.props.name]
一開始是 undefined
,所以得加一個默認值 ''
,否則 React 會認為是非受控組件而報錯。
import React, { Component } from "react";
import PropTypes from "prop-types";
import ctx from "./context";export default class FormInput extends Component {static contextType = ctx;static defaultProps = {type: "text",};static propTypes = {type: PropTypes.string.isRequired,name: PropTypes.string.isRequired,};render() {return (<div><inputtype={this.props.type}name={this.props.name}value={this.context.formData[this.props.name] || ""}onChange={(e) => {this.context.changeFormData(this.props.name, e.target.value);}}></input></div>);}
}
2.3,Form.Button
import React from "react";
import { Consumer } from "./context.js";export default function FormButton(props) {return (<Consumer>{(ctx) => {return <button onClick={() => ctx.submit()}>{props.children}</button>;}}</Consumer>);
}
3,使用
import React, { Component } from "react";
import Form from "./components/Form/index";export default class App extends Component {render() {return (<div><FormonSubmit={(formData) => {console.log(formData);}}><div><label>用戶名</label><Form.Input name="id"></Form.Input></div><div><label>用戶名</label><Form.Input name="pwd" type="password"></Form.Input></div><Form.Button>獲取FormData</Form.Button></Form></div>);}
}
最終,點擊按鈕就能獲取到 formData
更新后的數據。
以上。