React-v16.4.0
组件
组件创建及引用
函数定义
// 子组件
import React from 'react'
function HelloWorld(props) {
return <h1>Hello World!</h1>;
}
export default HelloWorld
// 父组件
import HelloWorld from './views/components/helloworld.js'
function App() {
return (
<div className="App">
<HelloWorld />
</div>
)
}
export default App
Class 定义
// 子组件
import React from 'react'
class HelloWorld extends React.Component {
render() {
return <span>Hello World!</span>
}
}
export default HelloWorld
// 父组件
import HelloWorld from './views/components/helloworld.js'
function App() {
return (
<div className="App">
<HelloWorld />
</div>
)
}
export default App
Props
Demo
// 父组件
import HelloWorld from './views/components/helloworld.js'
function App() {
return (
<div className="App">
<HelloWorld name="Runoob" /> // 直接在这里面去传
</div>
);
}
export default App;
// 子组件
import React from "react";
class HelloWorld extends React.Component {
constructor(props) {
super(props);
console.log('props', props); // {name: 'Runoob'}
}
getProps() {
console.log(this.props); // {name: 'Runoob'}
}
render() {
this.getProps()
return <span>{this.props.name}</span>;
}
}
export default HelloWorld;
默认 Props
// 父组件
import Props from './views/components/Props.js'
import './App.css'
function App() {
return (
<div className="App">
<Props/>
</div>
);
}
export default App;
// 子组件
import React from "react";
class Props extends React.Component {
constructor(props) {
super(props);
console.log('props', props); // {name: 'Runoob'}
}
getProps() {
console.log(this.props); // {name: 'Runoob'}
}
render() {
this.getProps()
return (
<div>
<h2>{this.props.name}</h2>
</div>
)
}
}
Props.defaultProps = {
name: 'Runoob' // 设置默认Props,避免父组件不传入。
};
export default Props;
State 和 Props 组合使用
class ShowName extends React.Component {
constructor(props) {
super(props);
}
render() {
return <h2>姓名是: {this.props.name}</h2>;
}
}
function ShowAge(props) {
return <h2>年龄是: {props.age}</h2>;
}
class Props extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "123",
age: 456,
};
}
render() {
return (
<div>
<ShowName name={this.state.name} />
<ShowAge age={this.state.age} />
</div>
);
}
}
export default Props;
Props 验证(就是限制是否必须,数据类型)
import PropTypes from "prop-types"; // 需要安装prop-types依赖,在React v15.5 版本后已经移到了 prop-types 库。
function ShowAge(props) {
return <h2>年龄是: {props.age}</h2>;
}
/**
* 这玩意儿和Vue的Props的type是一样的,格式不对的时候会warn
* react-jsx-dev-runtime.development.js:87 Warning: Failed prop type: Invalid prop `age` of type `string` supplied to `ShowAge`, expected `number`.
*/
ShowAge.propTypes = {
age: PropTypes.number,
};
class Props extends React.Component {
constructor(props) {
super(props);
this.state = {
age: "456", // 目前格式就是错误的.要num给了str
};
}
render() {
return (
<div>
<ShowAge age={this.state.age} />
</div>
);
}
}
验证器枚举
ShowAge.propTypes = {
// 可以声明 prop 为指定的 JS 基本数据类型,默认情况,这些数据是可选的
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalNode: PropTypes.node, // 可以被渲染的对象 numbers, strings, elements 或 array
optionalElement: PropTypes.element, // React 元素
optionalMessage: PropTypes.instanceOf(Message), // 用 JS 的 instanceof 操作符声明 prop 为类的实例。
optionalEnum: PropTypes.oneOf(["News", "Photos"]), // 用 enum 来限制 prop 只接受指定的值。
// 可以是多个对象类型中的一个
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Message),
]),
optionalArrayOf: PropTypes.arrayOf(PropTypes.number), // 指定类型组成的数组
optionalObjectOf: PropTypes.objectOf(PropTypes.number), // 指定类型的属性构成的对象
// 特定 shape 参数的对象
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number,
}),
requiredFunc: PropTypes.func.isRequired, // 任意类型加上 `isRequired` 来使 prop 不可空。
requiredAny: PropTypes.any.isRequired, // 不可空的任意类型
// 自定义验证器。如果验证失败需要返回一个 Error 对象。不要直接使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。
customProp: function (props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error("Validation failed!");
}
},
};
State
Demo
import React from "react";
class State extends React.Component {
constructor(props) {
super(props);
this.state = {
date: "",
};
}
componentDidMount() {
this.timerID = setInterval(() => this.changeState(), 1000);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
changeState() {
this.setState({ date: new Date().toLocaleTimeString() });
}
render() {
return (
<div>
<h2>当前时间是: {this.state.date}</h2>
</div>
);
}
}
export default State;
代码执行顺序
- 当
<Clock />被传递给ReactDOM.render()时,React 调用Clock组件的构造函数。 由于Clock需要显示当前时间,所以使用包含当前时间的对象来初始化this.state。 我们稍后会更新此状态。 - React 然后调用
Clock组件的render()方法。这是 React 了解屏幕上应该显示什么内容,然后 React 更新 DOM 以匹配Clock的渲染输出。 - 当
Clock的输出插入到 DOM 中时,React 调用componentDidMount()生命周期钩子。 在其中,Clock组件要求浏览器设置一个定时器,每秒钟调用一次tick()。 - 浏览器每秒钟调用
tick()方法。 在其中,Clock组件通过使用包含当前时间的对象调用setState()来调度 UI 更新。 通过调用setState(),React 知道状态已经改变,并再次调用render()方法来确定屏幕上应当显示什么。 这一次,render()方法中的this.state.date将不同,所以渲染输出将包含更新的时间,并相应地更新 DOM。 - 一旦
Clock组件被从 DOM 中移除,React 会调用componentWillUnmount()这个钩子函数,定时器也就会被清除。
数据流走向
State 父组件 ---> ShowDateView 子组件
import React from "react";
function ShowDateView(props) {
return <h2>当前时间是: {props.date}</h2>;
}
class State extends React.Component {
constructor(props) {
super(props);
this.state = {
date: "",
};
}
// 生命周期: 在组件挂载后(插入 DOM 树中)立即调用。
componentDidMount() {
this.timerID = setInterval(() => this.changeState(), 1000);
}
// 生命周期: 在组件卸载及销毁之前直接调用。
componentWillUnmount() {
clearInterval(this.timerID);
}
changeState() {
this.setState({ date: new Date().toLocaleTimeString() });
}
render() {
return (
<div>
<ShowDateView date={this.state.date} /> // 向子组件流向数据
</div>
);
}
}
export default State;
React 事件处理
React 元素的事件处理和 DOM 元素类似。但是有一点语法上的不同:
- React 事件绑定属性的命名采用驼峰式写法,而不是小写。
- 如果采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM 元素的写法)
HTML 通常写法是:
<button onclick="activateLasers()">激活按钮</button>
React 中写法为:
<button onClick={activateLasers}>激活按钮</button>
阻止默认行为(e.preventDefault)
在 React 中另一个不同是你不能使用返回 false 的方式阻止默认行为, 你必须明确使用 preventDefault。
例如,通常我们在 HTML 中阻止链接默认打开一个新页面,可以这样写:
<a href="#" onclick="console.log('点击链接'); return false"> 点我 </a>
在 React 的写法为:
import React from "react";
class Event extends React.Component {
constructor(opt) {
super(opt);
}
render() {
function handleClick(e) {
e.preventDefault(); // 这样写就可以阻止a标签的跳转行为
console.log("链接被点击了");
}
return (
<a href="#" target="_blank" onClick={handleClick}>
点击我
</a>
);
}
}
export default Event;
监视器(绑定 this)
使用 React 的时候通常你不需要使用 addEventListener 为一个已创建的 DOM 元素添加监听器。你仅仅需要在这个元素初始渲染的时候提供一个监听器。
当你使用 ES6 class 语法来定义一个组件的时候,事件处理器会成为类的一个方法。例如,下面的 Toggle 组件渲染一个让用户切换开关状态的按钮:
class Event extends React.Component {
constructor(opt) {
super(opt);
this.state = {
isToggleOn: true,
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState((prevState) => ({
isToggleOn: !prevState.isToggleOn,
}));
}
render() {
return (
<a type="button" onClick={this.handleClick}>
{this.state.isToggleOn ? "我是开启的状态" : "我是关闭的状态"}
</a>
);
}
}
export default Event;
JSX 回调函数中的 this,类的方法默认是不会绑定this的。如果你忘记绑定 this.handleClick 并把它传入 onClick, 当你调用这个函数的时候 this 的值会是 undefined。
监视器(不用绑定 this)
① 使用箭头函数,箭头函数的 this 指向定义者,而一般函数里的 this 指向其调用者;
class Event extends React.Component {
constructor(opt) {
super(opt);
this.state = {
isToggleOn: true,
};
}
handleClick = () => {
this.setState((prevState) => ({
isToggleOn: !prevState.isToggleOn,
}));
};
render() {
return (
<a type="button" onClick={this.handleClick}>
{this.state.isToggleOn ? "我是开启的状态" : "我是关闭的状态"}
</a>
);
}
}
export default Event;
② 在函数绑定时候处理
class Event extends React.Component {
constructor(opt) {
super(opt);
this.state = {
isToggleOn: true,
};
}
handleClick() {
this.setState((prevState) => ({
isToggleOn: !prevState.isToggleOn,
}));
}
render() {
return (
<a type="button" onClick={(e) => this.handleClick(e)}>
{this.state.isToggleOn ? "我是开启的状态" : "我是关闭的状态"}
</a>
);
}
}
export default Event;
向事件处理程序传递参数
通过箭头函数的方式,事件对象必须显式的进行传递
通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递。
class Event extends React.Component {
constructor(opt) {
super(opt);
this.state = {
isToggleOn: true,
word: "我点击了我自己",
};
}
handleClick(word, e) {
e.preventDefault();
alert(word);
}
render() {
return (
<div>
<a onClick={(e) => this.handleClick(this.state.word, e)}>箭头函数</a>
<a onClick={this.handleClick.bind(this, this.state.word)}>bind绑定</a>
</div>
);
}
}
React 条件渲染
React 中的条件渲染和 JavaScript 中的一致,使用 JavaScript 操作符 if 或条件运算符来创建表示当前状态的元素,然后让 React 根据它们来更新 UI。
import React from "react";
class TiaoJianXuanRan extends React.Component {
constructor(props) {
super(props);
this.isLogin = props.isLogin;
}
render() {
if (this.isLogin) {
return <h1>欢迎回来!</h1>;
} else {
return <h1>请先登录!</h1>;
}
}
}
export default TiaoJianXuanRan;
元素变量
通过变量 isLogin,来判断登录登出按钮展示的切换
function LoginBtn(props) {
return <div>{props.word}</div>;
}
function LogoutBtn(props) {
return <div>{props.word}</div>;
}
class TiaoJianXuanRan extends React.Component {
constructor(props) {
super(props);
this.handleLogin = this.handleLogin.bind(this);
this.handleLogout = this.handleLogout.bind(this);
this.state = {
isLogin: true,
};
}
handleLogin(e) {
this.setState({ isLogin: true });
}
handleLogout(e) {
this.setState({ isLogin: false });
}
render() {
let btn = null;
const isLogin = this.state.isLogin;
if (!isLogin) {
btn = <LoginBtn word={"暂时还没有登录---请先点击登录"} />;
} else {
btn = <LogoutBtn word={"您已登录---点击登出"} />;
}
return (
<div>
<Button type="primary" onClick={this.handleLogin}>
登录
</Button>
<Button type="primary" onClick={this.handleLogout}>
登出
</Button>
{btn}
</div>
);
}
}
与运算符 &&
function MaibBox(props) {
return <h1>{props.content}</h1>;
}
class TiaoJianXuanRan extends React.Component {
constructor(props) {
super(props);
this.state = {
content: "我是内容",
};
}
render() {
return (
<div>
<h1>下面的内容根据是否有 content来显示</h1>
{this.state.content && <MaibBox content={this.state.content} />}
</div>
);
}
}
export default TiaoJianXuanRan;
三目运算符
function MaibBox(props) {
return <h1>{props.content}</h1>;
}
class TiaoJianXuanRan extends React.Component {
constructor(props) {
super(props);
this.state = {
content: "我是内容",
};
}
render() {
return (
<div>
<h1>下面的内容根据是否有 content来显示</h1>
{this.state.content ? (
<MaibBox content={this.state.content} />
) : (
<MaibBox content={"没有content, 我是占位字符"} />
)}
</div>
);
}
}
export default TiaoJianXuanRan;
阻止组件渲染
function WarningBanner(props) {
if (props.warn) {
return null;
}
return <Alert message="warning Text" type="warning" />;
}
class TiaoJianXuanRan extends React.Component {
constructor(props) {
super(props);
this.state = {
showWarning: true,
};
this.handleShowWarning = this.handleShowWarning.bind(this);
}
handleShowWarning() {
this.setState((preState) => ({
showWarning: !preState.showWarning,
}));
}
render() {
return (
<div>
<Button type="primary" onClick={this.handleShowWarning}>
{this.state.showWarning ? "隐藏" : "显示"}
</Button>
<WarningBanner warn={this.state.showWarning} />
</div>
);
}
}
export default TiaoJianXuanRan;
React 列表 & Keys (v-for key)
import React from "react";
class ListAndKeys extends React.Component {
constructor(props) {
super(props);
this.state = {
numbers: [1, 2, 3, 4, 5],
};
}
render() {
const listItems = this.state.numbers.map((number) => (
<li key={number.toString()}>{number}</li>
));
console.log(listItems);
return <ul>{listItems}</ul>;
}
}
export default ListAndKeys;
Keys
Keys 可以在 DOM 中的某些元素被增加或删除的时候帮助 React 识别哪些元素发生了变化。因此你应当给数组中的每一个元素赋予一个确定的标识。 当元素没有确定的 id 时,你可以使用他的序列号索引 index 作为 key:
import React from "react";
class ListAndKeys extends React.Component {
constructor(props) {
super(props);
this.state = {
numbers: [1, 2, 3, 4, 5],
};
}
render() {
const listItems = this.state.numbers.map((number, index) => (
<li key={index}>{number}</li>
));
console.log(listItems);
return <ul>{listItems}</ul>;
}
}
用 keys 提取组件
元素的 key 只有在它和它的兄弟节点对比时才有意义。 比方说,如果你提取出一个 ListItem 组件,你应该把 key 保存在数组中的这个 元素上,而不是放在 ListItem 组件中的
元素上。
function ListItem(props) {
return <li>{props.value}</li>;
}
class ListAndKeys extends React.Component {
constructor(props) {
super(props);
this.state = {
numbers: [1, 2, 3, 4, 5],
};
}
render() {
const listItems = this.state.numbers.map((number, index) => (
<ListItem key={index} value={number} />
));
return <ul>{listItems}</ul>;
}
}
export default ListAndKeys;
key 应该唯一
数组元素中使用的 key 在其兄弟之间应该是独一无二的。然而,它们不需要是全局唯一的。当生成两个不同的数组时,可以使用相同的键。
key 会作为给 React 的提示,但不会传递给你的组件。如果您的组件中需要使用和 key 相同的值
Post 组件可以读出 props.id,但是不能读出 props.key。
const content = posts.map((post) => (
<Post key={post.id} id={post.id} title={post.title} />
));
在 jsx 中嵌入 map()
function ListItem(props) {
return <li>{props.value}</li>;
}
class ListAndKeys extends React.Component {
constructor(props) {
super(props);
this.state = {
numbers: [1, 2, 3, 4, 5],
};
}
render() {
return (
<ul>
{this.state.numbers.map((number, index) => (
<ListItem key={index} value={number} />
))}
</ul>
);
}
}
export default ListAndKeys;
React 组件 API
设置状态:setState 替换状态:replaceState 设置属性:setProps 替换属性:replaceProps 强制更新:forceUpdate 获取 DOM 节点:findDOMNode 判断组件挂载状态:isMounted
设置状态:setState
不能在组件内部通过 this.state 修改状态,因为该状态会在调用 setState()后被替换。
setState()并不会立即改变 this.state,而是创建一个即将处理的 state。setState()并不一定是同步的,为了提升性能 React 会批量执行 state 和 DOM 渲染。
setState()总是会触发一次组件重绘,除非在 shouldComponentUpdate()中实现了一些条件渲染逻辑。
import React from "react";
class ReactAPI extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "小红",
age: 12,
};
}
handleNameChange = (e) => {
this.setState({ name: e.target.value }, () => {
console.log(this.state); // {name: '小红11111', age: 12}
});
};
render() {
return (
<div>
<input
value={this.state.name}
type="text"
onChange={this.handleNameChange}
/>
<h1>你好:{this.state.name}</h1>
</div>
);
}
}
export default ReactAPI;
替换状态:replaceState
设置属性:setProps
替换属性:replaceProps
强制更新:forceUpdate
获取 DOM 节点:findDOMNode
判断组件挂载状态:isMounted
React 组件生命周期
componentDidMount 所有 AJAX 请求以及 DOM 或状态更新都应在 componentDidMount()方法块中进行编码 shouldComponentUpdate 方法允许我们退出复杂的反应更新生命周期,以避免在每个 re-render 上一次又一次地调用它。
挂载组件-Mounting
- constructor(): 在 React 组件挂载之前,会调用它的构造函数。
- getDerivedStateFromProps(): 在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。
- render(): render() 方法是 class 组件中唯一必须实现的方法。
- componentDidMount(): 在组件挂载后(插入 DOM 树中)立即调用。
class LifeCycle extends React.Component {
// 在 React 组件挂载之前,会调用它的构造函数。
constructor(props) {
super(props);
this.state = { favoritesite: "runoob" };
console.log("第一步执行");
}
/**
* 在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。
* @param {*} nextProps 下一次props
* @param {*} nextState 下一次state
* @returns 默认情况下,它返回true,如果返回false,则不会调用render(),componentWillUpdate()和componentDidUpdate()方法。
*/
static getDerivedStateFromProps(nextProps, nextState) {
console.log("第二步执行");
return { favoritesite: nextProps.favsite };
}
// render() 方法是 class 组件中唯一必须实现的方法。
render() {
console.log("第三步执行");
return <h1>我喜欢的网站是 {this.state.favoritesite}</h1>;
}
// 在组件挂载后(插入 DOM 树中)立即调用。
componentDidMount() {
console.log("第四步执行");
}
}
export default LifeCycle;
更新组件-Updating
class LifeCycle extends React.Component {
constructor(props) {
super(props);
this.state = { favoritesite: "Baidu" };
console.log("第一步执行-->constructor");
}
handleWebChange = (e) => {
this.setState({ favoritesite: "Google" });
};
/**
* 在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。
* @param {*} nextProps 下一次props
* @param {*} nextState 下一次state
* @returns 默认情况下,它返回true,如果返回false,则不会调用render(),componentWillUpdate()和componentDidUpdate()方法。
*/
static getDerivedStateFromProps(nextProps, nextState) {
console.log("第二步执行-->getDerivedStateFromProps");
return { favoritesite: nextState.favoritesite };
}
// 当 props 或 state 发生变化时,shouldComponentUpdate() 会在渲染执行之前被调用。
shouldComponentUpdate() {
console.log("第三步执行-->shouldComponentUpdate");
return true;
}
// render() 方法是 class 组件中唯一必须实现的方法。
render() {
console.log("第四步执行-->render");
return (
<div>
<h1>我喜欢的网站是: {this.state.favoritesite}</h1>
<button onClick={this.handleWebChange}>改变我喜欢的网站为Google</button>
</div>
);
}
/**
* 在最近一次渲染输出(提交到 DOM 节点)之前调用。
* @param {*} prevProps 先前的道具传递到组件
* @param {*} prevState 组件的先前状态
* @returns
*/
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log("第五步执行-->getSnapshotBeforeUpdate");
return null;
}
/**
* 在更新后会被立即调用。
* @param {*} prevProps 先前的道具传递到组件
* @param {*} prevState 组件的先前状态
* @param {*} snapshot getSnapshotBeforeUpdate()方法返回的值
*/
componentDidUpdate(prevProps, prevState, snapshot) {
console.log("第六步执行-->componentDidUpdate");
}
}
export default LifeCycle;
卸载组件-Unmounting
class LifeCycle extends React.Component {
constructor(props) {
super(props);
this.state = { show: true };
}
delHeader = () => {
this.setState({ show: false });
};
render() {
let myheader;
if (this.state.show) {
myheader = <Child />;
}
return (
<div>
{myheader}
<button type="button" onClick={this.delHeader}>
删除标题组建
</button>
</div>
);
}
}
class Child extends React.Component {
componentWillUnmount() {
alert("标题组件即将卸载。");
}
render() {
return <h1>Hello Runoob!</h1>;
}
}
export default LifeCycle;
React AJAX
React 组件的数据可以通过 componentDidMount 方法中的 Ajax 来获取,当从服务端获取数据时可以将数据存储在 state 中,再用 this.setState 方法重新渲染 UI。
当使用异步加载数据时,在组件卸载前使用 componentWillUnmount 来取消未完成的请求。
import React from "react";
import $ from "jquery";
class ReactAjax extends React.Component {
constructor(props) {
super(props);
this.state = { username: "", lastGistUrl: "" };
}
componentDidMount() {
this.serverRequest = $.get(
this.props.source,
function (result) {
var lastGist = result[0];
this.setState({
username: lastGist.owner.login,
lastGistUrl: lastGist.html_url,
});
}.bind(this)
);
}
componentWillUnmount() {
this.serverRequest.abort();
}
render() {
return (
<div>
<p>{this.state.username} 用户最新的 Gist 共享地址</p>
<a href={this.state.lastGistUrl}>{this.state.lastGistUrl}</a>
</div>
);
}
}
export default ReactAjax;
React 表单与事件
input 的 onChange (示例 1)
import React from "react";
class FormEvent extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "Hello World",
};
}
changeValue = (event) => {
this.setState({ value: event.target.value });
};
render() {
return (
<div>
<input
type="text"
value={this.state.value}
onChange={this.changeValue}
/>
<h4>{this.state.value}</h4>
</div>
);
}
}
export default FormEvent;
input 的 onChange (示例 2)
class Content extends React.Component {
constructor(props) {
super(props);
console.log(props);
}
render() {
return (
<div>
<input
type="text"
value={this.props.myDataProp}
onChange={this.props.updateStateProp}
/>
<h4>{this.props.myDataProp}</h4>
</div>
);
}
}
class FormEvent extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "Hello World",
};
}
changeValue = (event) => {
this.setState({ value: event.target.value });
};
render() {
return (
<div>
<Content
myDataProp={this.state.value}
updateStateProp={this.changeValue}
/>
</div>
);
}
}
export default FormEvent;
Select 下拉菜单
class FormEvent extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "11",
};
}
handleSubmit = (event) => {
alert("表单提交了!");
event.preventDefault();
};
handleChange = (event) => {
this.setState({ value: event.target.value });
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<select value={this.state.value} onChange={this.handleChange}>
<option value="11">11</option>
<option value="22">22</option>
<option value="33">33</option>
<option value="44">44</option>
</select>
<h4>{this.state.value}</h4>
<input type="submit" value="提交" />
</form>
);
}
}
export default FormEvent;
多个表单
class FormEvent extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
value: "11",
};
}
handleInputChange = (event) => {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
const name = target.name;
this.setState({ [name]: value });
};
render() {
return (
<form>
<label htmlFor="">
<input
type="checkbox"
name="isGoing"
onChange={this.handleInputChange}
checked={this.state.isGoing}
/>
</label>
<label htmlFor="">
<input
type="text"
name="value"
onChange={this.handleInputChange}
value={this.state.value}
/>
</label>
<h1>{Number(this.state.isGoing)}</h1>
<h1>{this.state.value}</h1>
</form>
);
}
}
export default FormEvent;
React 事件
当你需要从子组件中更新父组件的 state 时,你需要在父组件通过创建事件句柄 (handleChange) ,并作为 prop (updateStateProp) 传递到你的子组件上
class Children extends React.Component {
render() {
return (
<div>
<button onClick={this.props.clickChildren}>点我-我是子组件</button>
<h4>{this.props.childrenData}</h4>
</div>
);
}
}
class FormEvent extends React.Component {
constructor(props) {
super(props);
this.state = { value: "11" };
}
clickChildren = () => {
this.setState({
value: "我在父组件里面点了子组件的按钮",
});
};
render() {
return (
<div>
<Children
childrenData={this.state.value}
clickChildren={this.clickChildren}
/>
</div>
);
}
}
export default FormEvent;
React Refs
React 支持一种非常特殊的属性 Ref ,你可以用来绑定到 render() 输出的任何组件上。
这个特殊的属性允许你引用 render() 返回的相应的支撑实例( backing instance )。这样就可以确保在任何时间总是拿到正确的实例。
demo
class Children extends React.Component {
render() {
return (
<div>
<h4>我是子组件</h4>
</div>
);
}
}
class FormEvent extends React.Component {
constructor(props) {
super(props);
}
clickBtn = () => {
this.refs.myInput.focus();
};
render() {
return (
<div>
<input type="text" ref="myInput" />
<Children ref="Children" />
<button onClick={this.clickBtn}>点击聚焦输入框</button>
</div>
);
}
componentDidMount() {
const input = this.refs.myInput;
console.log(input); // 返回了输入框的 <input type="text">
const Children = this.refs.Children;
console.log(Children); // 返回组件
// context: {}
// props: {}
// refs: {}
// state: null
// updater: {isMounted: ƒ, enqueueSetState: ƒ, enqueueReplaceState: ƒ, enqueueForceUpdate: ƒ}
// _reactInternalInstance: {_processChildContext: ƒ}
// _reactInternals: FiberNode {tag: 1, key: null, stateNode: Children, elementType: ƒ, type: ƒ, …}
// isMounted
}
}
export default FormEvent;