React 面向组件编程
1-基本理解和使用
1.1-函数式组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 1. 创建函数式组件
function MyComponent(params) {
console.log(this); // undefined ---> 是因为 babel 编译后是严格模式,那么this就不能指向window了,
return <h2>我是用函数定义的组件(适用于简单组件的定义)</h2>;
}
// 2. 渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test"));
/**
* 执行了 ReactDOM.render(<MyComponent />, document.getElementById("test"));
* 1. React会解析组件标签,找MyComponent组件
* 2. 发现组件是函数定义的,那么就调用这个函数,
* 3. 将返回的虚拟dom转换成真实dom.呈现在页面上
*/
</script>
</body>
</html>
1.2-类式组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 1. 类式组件
class MyComponent extends React.Component {
render() {
// render 方法放在了 ---> 类 MyComponent 的原型对象上; 供实例使用
// render 的this是谁 ---> MyComponent 的实例对象
console.log(this); // MyComponent {props: {…}, context: {…}, refs: {…}, updater: {…}, _reactInternalFiber: FiberNode, …}
return <h1>我是类定义的组件,适用于复杂组件</h1>;
}
}
// 2. 渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test"));
/**
* 执行了 ReactDOM.render(<MyComponent />, document.getElementById("test"));
* 1. React会解析组件标签,找MyComponent组件
* 2. 发现组件是函数定义的,那么就new出来该类的实例,并通过该实例调用到原型的render方法,
* 3. 将返回的虚拟dom转换成真实dom.呈现在页面上
*/
</script>
</body>
</html>
02-state
2.1-state 基础使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title></title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 1. 创建组件
class Weather extends React.Component {
// constructor 构造器执行几次?-->new 几次就会执行几次
constructor(props) {
super(props);
// 初始化状态
this.state = {
isHot: true,
wind: "微风",
};
// 这样处理是为了解决静态方法内无法拿到类的this,解决this指向的问题
this.changeWeather = this.changeWeather.bind(this);
}
/**
* changeWeather放在哪里?---Watcher的原型对象上,供实例使用
* 由于changeWeather方法作为onClick的回调,所以不是实例调用的而是直接调用的
* 类中的方法默认开启了严格模式,所以changeWeather里面的this是undefined
*
*/
// changeWeather 执行几次? ---> 点几次调用几次
changeWeather() {
const isHot = this.state.isHot;
// state里面的状态里面的数据要修改需要使用 setState 方法
// this.state.isHot = !isHot // 错误的写法
this.setState({
isHot: !isHot,
});
}
// render 执行几次?--> 执行 n+1 次, n 是状态更新的次数,每次 state 更新, render 都会执行
render() {
// 读取状态
const { isHot, wind } = this.state;
return (
<div>
<button onClick={this.changeWeather}>改变天气</button>
<h1>
今天的天气好: {isHot ? "热" : "冷"},{wind}
</h1>
</div>
);
}
}
// 2. 渲染组件到页面
ReactDOM.render(<Weather />, document.getElementById("test"));
</script>
</body>
</html>
2.2-state 简写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title></title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
class Weather extends React.Component {
// 初始化状态
state = { isHot: true, wind: "微风" };
/**
* 自定义方法:---以后都成 赋值语句的形式+箭头函数
* this执行就会到了watcher了
* 这样的写法就是把 changeWeather 放在自身,而不是放在原型函数上
*/
changeWeather = () => {
console.log(this); // Weather {props: {…}, context: {…}, refs: {…}, updater: {…}, state: {…}, …}
const isHot = this.state.isHot;
this.setState({ isHot: !isHot });
};
render() {
const { isHot, wind } = this.state;
return (
<div>
<h1 onClick={this.changeWeather}>
今天的天气好: {isHot ? "热" : "冷"},{wind}
</h1>
</div>
);
}
}
// 2. 渲染组件到页面
ReactDOM.render(<Weather />, document.getElementById("test"));
</script>
</body>
</html>
03-props
3.1-props 基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 1. 创建函数式组件
class MyComponent extends React.Component {
render() {
return (
<ul>
<li>姓名{this.props.name}</li>
<li>年龄{this.props.age}</li>
<li>性别{this.props.sex}</li>
</ul>
);
}
}
// 2. 渲染组件到页面
ReactDOM.render(
<MyComponent name="tom" age="12" sex="男" />,
document.getElementById("test")
);
</script>
</body>
</html>
3.2-对 props 进行限制
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script src="../React-js/prop-types.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 1. 创建函数式组件
class MyComponent extends React.Component {
// props是只读的
render() {
return (
<ul>
<li>姓名{this.props.name}</li>
<li>年龄{this.props.age}</li>
<li>性别{this.props.sex}</li>
</ul>
);
}
}
// 对标签属性进行必要性的限制
MyComponent.propTypes = {
name: PropTypes.string.isRequired, // 限制姓名为字符串且必填
name: PropTypes.string, // 限制必须字符串
age: PropTypes.number, // 限制必须数字
speak: PropTypes.func, // 限制必须为函数
};
// 指定属性的默认值
MyComponent.defaultProps = {
sex: "不男不女",
age: 18,
};
const info = { name: "123", age: 13 };
ReactDOM.render(
<MyComponent {...info} speak={speak} />,
document.getElementById("test1")
);
function speak(params) {
console.log("我说话了");
}
</script>
</body>
</html>
3.3-props 简写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script src="../React-js/prop-types.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 1. 创建函数式组件
class MyComponent extends React.Component {
// 对标签属性进行必要性的限制
static propTypes = {
name: PropTypes.string.isRequired, // 限制姓名为字符串且必填
name: PropTypes.string, // 限制必须字符串
age: PropTypes.number, // 限制必须数字
speak: PropTypes.func, // 限制必须为函数
};
// 指定属性的默认值
static defaultProps = {
sex: "不男不女",
age: 18,
};
// props是只读的
render() {
return (
<ul>
<li>姓名{this.props.name}</li>
<li>年龄{this.props.age}</li>
<li>性别{this.props.sex}</li>
</ul>
);
}
}
const info = { name: "123", age: 13 };
ReactDOM.render(
<MyComponent {...info} speak={speak} />,
document.getElementById("test1")
);
function speak(params) {
console.log("我说话了");
}
</script>
</body>
</html>
3.4-props 在构造函数中情况
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script src="../React-js/prop-types.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 1. 创建函数式组件
class MyComponent extends React.Component {
// props是只读的
render() {
return (
<ul>
<li>姓名{this.props.name}</li>
<li>年龄{this.props.age}</li>
<li>性别{this.props.sex}</li>
</ul>
);
}
}
const info = { name: "123", age: 13 };
ReactDOM.render(
<MyComponent {...info} speak={speak} />,
document.getElementById("test1")
);
function speak(params) {
console.log("我说话了");
}
</script>
</body>
</html>
3.5-props 在函数值组件中使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script src="../React-js/prop-types.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 1. 创建函数式组件
function MyComponent(props) {
const { name, age, sex } = props;
return (
<ul>
<li>姓名{name}</li>
<li>年龄{age}</li>
<li>性别{sex}</li>
</ul>
);
}
// 对标签属性进行必要性的限制
MyComponent.propTypes = {
name: PropTypes.string.isRequired, // 限制姓名为字符串且必填
name: PropTypes.string, // 限制必须字符串
age: PropTypes.number, // 限制必须数字
speak: PropTypes.func, // 限制必须为函数
};
// 指定属性的默认值
MyComponent.defaultProps = {
sex: "不男不女",
age: 18,
};
const info = { name: "123", age: 13 };
ReactDOM.render(
<MyComponent {...info} />,
document.getElementById("test1")
);
</script>
</body>
</html>
04-refs
4.1-字符串形式 refs 的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
/**
* 字符串的refs存在效率上的问题,不推荐使用
*/
// 1. 创建函数式组件
class MyComponent extends React.Component {
// 展示左侧输入框的数据
showData = () => {
const { input1 } = this.refs;
let value1 = input1.value;
console.log(value1);
};
// 展示右侧输入框的数据
showData2 = () => {
const { input2 } = this.refs;
let value2 = input2.value;
console.log(value2);
};
render() {
return (
<div>
<input
ref="input1"
type="text"
placeholder="点击按钮提示数据"
></input>
<button onClick={this.showData}>点我提示左侧的数据</button>
<input
ref="input2"
onBlur={this.showData2}
type="text"
placeholder="失去焦点提示数据"
></input>
</div>
);
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
4.2-回调形式 refs 的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
/**
* 字符串的refs存在效率上的问题,不推荐使用
*/
// 1. 创建函数式组件
class MyComponent extends React.Component {
// 展示左侧输入框的数据
showData = () => {
const { input1 } = this;
let value1 = input1.value;
alert(value1);
};
// 展示右侧输入框的数据
showData2 = () => {
const { input2 } = this;
let value2 = input2.value;
alert(value2);
};
render() {
return (
<div>
<input
ref={(c) => (this.input1 = c)}
type="text"
placeholder="点击按钮提示数据"
></input>
<button onClick={this.showData}>点我提示左侧的数据</button>
<input
ref={(c) => (this.input2 = c)}
onBlur={this.showData2}
type="text"
placeholder="失去焦点提示数据"
></input>
</div>
);
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
4.3-回调形式 refs 的回调执行次数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
/**
* 字符串的refs存在效率上的问题,不推荐使用
*/
// 1. 创建函数式组件
class MyComponent extends React.Component {
state = { isHot: true };
// 展示左侧输入框的数据
showData = () => {
const { input1 } = this;
let value1 = input1.value;
alert(value1);
};
changeWeather = () => {
const { isHot } = this.state;
this.setState({
isHot: !isHot,
});
};
saveInput = (c) => {
this.input1 = c;
console.log(c);
};
render() {
const { isHot } = this.state;
return (
<div>
<h2>今天天气很{isHot ? "热" : "冷"}</h2>
{/*这种写法有个问题,就是更新时候,这个console.log(c)会执行两次,第一次c是null,第二才是这个dom结构*/}
{/*<input ref={c => { this.input1 = c; console.log(c); }} type="text" placeholder="点击按钮提示数据"></input>*/}
{/*这种写法是做好的,只会执行一次,但是没必要*/}
<input
ref={this.saveInput}
type="text"
placeholder="点击按钮提示数据"
></input>
<button onClick={this.showData}>点我提示左侧的数据</button>
<button onClick={this.changeWeather}>点我切换天气</button>
</div>
);
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
4.4-createRef 形式 refs 的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 1. 创建函数式组件
class MyComponent extends React.Component {
/**
* React.createRef调用后返回䘝容器,该容器可以存储被ref所标识的节点
* 该容器是专人专用,只能存一个节点
*/
myRef1 = React.createRef();
myRef2 = React.createRef();
// 展示左侧输入框的数据
showData = () => {
alert(this.myRef1.current.value);
};
// 展示右侧输入框的数据
showData2 = () => {
alert(this.myRef2.current.value);
};
render() {
return (
<div>
<input
ref={this.myRef1}
type="text"
placeholder="点击按钮提示数据"
></input>
<button onClick={this.showData}>点我提示左侧的数据</button>
<input
ref={this.myRef2}
onBlur={this.showData2}
type="text"
placeholder="失去焦点提示数据"
></input>
</div>
);
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
4.5-.事件处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 1. 创建函数式组件
class MyComponent extends React.Component {
/**
* 1. 通过 onXxx 属性指定事件处理函数(注意大小写)
* 1.1 React 使用的是自定义(合成)事件,而不是使用的原生DOM的事件 --- 为了更好的兼容性
* 1.2 React 中的事件是通过事件委托方式处理的(委托给组件的最外层) --- 为了高效
* 2. 通过 event.target 得到发生事件的 DOM 元素 --- 不要过度使用 ref
*/
//创建ref容器
myRef1 = React.createRef();
// 展示左侧输入框的数据
showData = () => {
alert(this.myRef1.current.value);
};
// 展示右侧输入框的数据
showData2 = (event) => {
alert(event.target.value);
};
render() {
return (
<div>
<input
ref={this.myRef1}
type="text"
placeholder="点击按钮提示数据"
></input>
<button onClick={this.showData}>点我提示左侧的数据</button>
<input
onBlur={this.showData2}
type="text"
placeholder="失去焦点提示数据"
></input>
</div>
);
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
5-React 中收集表单数据
5.1-非受控组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 1. 创建函数式组件
class MyComponent extends React.Component {
handleSubmit = (e) => {
const { username, password } = this;
e.preventDefault(); // 可以阻止表单的默认跳转
console.log(username.value, password.value);
};
render() {
return (
<form onSubmit={this.handleSubmit}>
用户名:{" "}
<input
ref={(c) => (this.username = c)}
type="text"
name="username"
/>
密码: <input
ref={(c) => (this.password = c)}
type="password"
password="password"
/>
<button>登录</button>
</form>
);
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
5.2-受控组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
/**
* 手控组件的好处就是省掉了过多的ref
*/
// 1. 创建函数式组件
class MyComponent extends React.Component {
state = {
username: "",
password: "",
};
handleSubmit = (e) => {
e.preventDefault(); // 可以阻止表单的默认跳转
const { username, password } = this.state;
console.log(username, password);
};
// 保存用户名到state
changeUsername = (e) => {
this.setState({ username: e.target.value });
};
// 保存密码到state
changePassword = (e) => {
this.setState({ password: e.target.value });
};
render() {
return (
<form onSubmit={this.handleSubmit}>
用户名:{" "}
<input
onChange={this.changeUsername}
type="text"
name="username"
/>
密码: <input
onChange={this.changePassword}
type="password"
password="password"
/>
<button>登录</button>
</form>
);
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
6-高阶函数与函数柯里化
6.1-高阶函数和函数柯里化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
/**
* 高阶函数: 如果一个函数符合下面两个规范中的任何一个,那么该函数就是高阶函数
* 1. 若A函数,接收的参数是一个函数,那么A函数就称为高阶函数
* 2. 若A函数,调用的返回值依然是一个函数,那么A函数就称为高阶函数
* 常见的高阶函数
* 1. Promise new Promise(()=>{})
* 2. setTimeout
* 3. arr.map 等等
*
*
* 函数的柯里化: 通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码方式
*/
// 1. 创建函数式组件
class MyComponent extends React.Component {
state = {
username: "",
password: "",
};
// 提交表单
handleSubmit = (event) => {
event.preventDefault(); // 可以阻止表单的默认跳转
const { username, password } = this.state;
console.log(username, password);
};
// 保存表单项的数据到状态中
saveFormData = (dataType) => {
return (event) => {
this.setState({ [dataType]: event.target.value });
};
};
render() {
return (
<form onSubmit={this.handleSubmit}>
用户名:{" "}
<input
onChange={this.saveFormData("username")}
type="text"
name="username"
/>
密码: <input
onChange={this.saveFormData("password")}
type="password"
password="password"
/>
<button>登录</button>
</form>
);
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
6.2-不用高阶函数和函数柯里化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 1. 创建函数式组件
class MyComponent extends React.Component {
state = {
username: "",
password: "",
};
// 提交表单
handleSubmit = (event) => {
event.preventDefault(); // 可以阻止表单的默认跳转
const { username, password } = this.state;
console.log(username, password);
};
// 保存表单项的数据到状态中
saveFormData = (dataType, event) => {
this.setState({ [dataType]: event.target.value });
};
render() {
return (
<form onSubmit={this.handleSubmit}>
用户名:{" "}
<input
onChange={(event) => {
this.saveFormData("username", event);
}}
type="text"
name="username"
/>
密码: <input
onChange={(event) => {
this.saveFormData("password", event);
}}
type="password"
password="password"
/>
<button>登录</button>
</form>
);
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
7-组件的生命周期
旧生命周期
新生命周期
7-1.引出生命周期
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test"></div>
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 生命周期回调函数 === 生命周期钩子函数 === 生周期函数 === 生命周期钩子
// 1. 创建函数式组件
class MyComponent extends React.Component {
state = { opacity: 1 };
death = () => {
// 卸载组件
ReactDOM.unmountComponentAtNode(document.getElementById("test1"));
};
// 组件挂在完毕时候调用
componentDidMount() {
this.timer = setInterval(() => {
let { opacity } = this.state;
opacity -= 0.1;
if (opacity <= 0) {
opacity = 1;
}
this.setState({ opacity });
}, 200);
}
// 组件将要卸载时候调用
componentWillUnmount() {
clearInterval(this.timer);
}
// 初始化渲染, 状态更新之后
render() {
return (
<div>
<h2 style={{ opacity: this.state.opacity }}>
React学不会怎么办?
</h2>
<button onClick={this.death}>不活了!</button>
</div>
);
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
7-2.生命周期-挂载(旧)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 生命周期回调函数 === 生命周期钩子函数 === 生周期函数 === 生命周期钩子
// 1. 创建函数式组件
class MyComponent extends React.Component {
// 构造器 (第一步)
constructor(props) {
super(props);
// 初始化状态
this.state = { count: 0 };
console.log("挂载 第一步 ---> constructor");
}
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById("test1"));
};
// 组件将要挂载时候调用 (第二步)
componentWillMount() {
console.log("挂载 第二步 ---> componentWillMount");
}
// 初始化渲染, 状态更新之后
render() {
console.log("挂载 第三步 ---> render");
return (
<div>
<h2>当前求和为: {this.state.count}</h2>
<button onClick={this.death}>卸载组件</button>
</div>
);
}
// 组件挂载完毕时候调用
componentDidMount() {
console.log("挂载 第四步 ---> componentDidMount");
}
// 组件将要卸载时候调用
componentWillUnmount() {
console.log("挂载 第五步 ---> componentWillUnmount");
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
7-3.生命周期-setState 更新(旧)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 生命周期回调函数 === 生命周期钩子函数 === 生周期函数 === 生命周期钩子
// 1. 创建函数式组件
class MyComponent extends React.Component {
// 构造器 (第一步)
constructor(props) {
super(props);
// 初始化状态
this.state = { count: 0 };
}
add = () => {
const { count } = this.state;
this.setState({
count: count + 1,
});
console.log("更新 第一步 ---> setState");
};
// 控制组件更新的开关
shouldComponentUpdate() {
console.log("更新 第二步 ---> shouldComponentUpdate");
return true;
}
componentWillUpdate() {
console.log("更新 第三步 ---> componentWillUpdate");
}
// 初始化渲染, 状态更新之后
render() {
console.log("更新 第四步 ---> render");
return (
<div>
<h2>当前求和为: {this.state.count}</h2>
<button onClick={this.add}>点我+1</button>
</div>
);
}
componentDidUpdate() {
console.log("更新 第五步 ---> componentDidUpdate");
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
7-4.生命周期-forceUpdate 更新(旧)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 生命周期回调函数 === 生命周期钩子函数 === 生周期函数 === 生命周期钩子
// 1. 创建函数式组件
class MyComponent extends React.Component {
// 构造器 (第一步)
constructor(props) {
super(props);
// 初始化状态
this.state = { count: 0 };
}
// 强制更新按钮(不会走到shouldComponentUpdate)
force = () => {
this.forceUpdate();
console.log("更新 第一步 ---> forceUpdate");
};
componentWillUpdate() {
console.log("更新 第二步 ---> componentWillUpdate");
}
// 初始化渲染, 状态更新之后
render() {
console.log("更新 第三步 ---> render");
return (
<div>
<h2>当前求和为: {this.state.count}</h2>
<button onClick={this.force}>不更新数据强制更新页面</button>
</div>
);
}
componentDidUpdate() {
console.log("更新 第四步 ---> componentDidUpdate");
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
7-5.生命周期-父组件 render 更新(旧)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 生命周期回调函数 === 生命周期钩子函数 === 生周期函数 === 生命周期钩子
// 父组件A
class A extends React.Component {
state = { carName: "奔驰" };
changeCar = () => {
this.setState({ carName: "奥迪" });
};
render() {
return (
<div>
<h1>A</h1>
<button onClick={this.changeCar}>换车</button>
<B carName={this.state.carName} />
</div>
);
}
}
// 子组件B
class B extends React.Component {
// 这个钩子第一次传的不算
componentWillReceiveProps(props) {
console.log("子组件更新 第一步 ---> componentWillReceiveProps");
console.log(props);
}
// 控制组件更新的开关
shouldComponentUpdate() {
console.log("子组件更新 第二步 ---> shouldComponentUpdate");
return true;
}
componentWillUpdate() {
console.log("子组件更新 第三步 ---> componentWillUpdate");
}
render() {
console.log("子组件更新 第四步 ---> render");
return <div>B -- {this.props.carName}</div>;
}
componentDidUpdate() {
console.log("子组件更新 第五步 ---> componentDidUpdate");
}
}
// 2.渲染组件到页面
ReactDOM.render(<A />, document.getElementById("test1"));
</script>
</body>
</html>
7-6.生命周期总结(旧)
/**
* 常用:
* 1. componentDidMount() 一般做一些初始化的事儿,例如开始定制器或者发送网络请求或者订阅消息
* 2. componentWillUnmount() 一般做一些收尾的事儿,例如取消定时器
*
* 1. 初始化阶段: 由 ReactDOM.render() 触发---初次渲染
* 1. constructor()
* 2. componentWillMount()
* 3. render()
* 4. componentDidMount()
* 2. 更新阶段: 由组件内部 setState() 或者父组件 render() 触发
* 1. shouldComponentUpdate()
* 2. componentWillUpdate()
* 3. render()
* 4. componentDidMount()
* 3. 更新阶段: 由组件内部 forceUpdate() 触发
* 1. componentWillUpdate()
* 2. render()
* 3. componentDidMount()
* 4. 父组件Props更新: 由父组件Props更新导致子组件更新
* 1. componentWillReceiveProps()
* 2. shouldComponentUpdate()
* 3. componentWillUpdate()
* 4. render()
* 5. componentDidMount()
* 5. 卸载组件: 由 ReactDOM.unmountComponentAtNode() 触发
* 1. componentWillUnmount()
*/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 生命周期回调函数 === 生命周期钩子函数 === 生周期函数 === 生命周期钩子
// 1. 创建函数式组件
class MyComponent extends React.Component {
// 构造器 (第一步)
constructor(props) {
super(props);
// 初始化状态
this.state = { count: 0 };
console.log("挂载 第一步 ---> constructor");
}
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById("test1"));
};
// 组件将要挂载时候调用 (第二步)
componentWillMount() {
console.log("挂载 第二步 ---> componentWillMount");
}
// 初始化渲染, 状态更新之后
render() {
console.log("挂载 第三步 ---> render");
return (
<div>
<h2>当前求和为: {this.state.count}</h2>
<button onClick={this.death}>卸载组件</button>
</div>
);
}
// 组件挂载完毕时候调用
componentDidMount() {
console.log("挂载 第四步 ---> componentDidMount");
}
// 组件将要卸载时候调用
componentWillUnmount() {
console.log("挂载 第五步 ---> componentWillUnmount");
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
7-7.生命周期-挂载(新)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/17/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/17/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 所有带 will 的钩子函数都需要加上 UNSAFE_
// 1. 创建函数式组件
/***
* 更新了三个钩子函数
* 1. componentWillMount UNSAFE_componentWillMount
* 2. componentWillUpdate UNSAFE_componentWillUpdate
* 3. componentWillReceiveProps componentWillReceiveProps
*/
class MyComponent extends React.Component {
// 构造器 (第一步)
constructor(props) {
super(props);
// 初始化状态
this.state = { count: 0 };
console.log("挂载 第一步 ---> constructor");
}
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById("test1"));
};
// 组件将要挂载时候调用 - 旧 (第二步)
componentWillMount() {
console.log("挂载 第二步 ---> componentWillMount");
}
// 组件将要挂载时候调用 - 新 (第二步)
UNSAFE_componentWillMount() {
console.log("挂载 第二步 ---> UNSAFE_componentWillMount");
}
// 组件将要更新数据时调用 - 旧
componentWillUpdate() {
console.log("子组件更新 第三步 ---> componentWillUpdate");
}
// 组件将要更新数据时调用 - 新
UNSAFE_componentWillUpdate() {
console.log("子组件更新 第三步 ---> UNSAFE_componentWillUpdate");
}
// 当props发生变化时调用 - 旧
// 这个钩子第一次传的不算
componentWillReceiveProps(props) {
console.log("子组件更新 第一步 ---> componentWillReceiveProps");
console.log(props);
}
// 当props发生变化时调用 - 新
// 这个钩子第一次传的不算
UNSAFE_componentWillReceiveProps(props) {
console.log(
"子组件更新 第一步 ---> UNSAFE_componentWillReceiveProps"
);
console.log(props);
}
// 初始化渲染, 状态更新之后
render() {
console.log("挂载 第三步 ---> render");
return (
<div>
<h2>当前求和为: {this.state.count}</h2>
<button onClick={this.death}>卸载组件</button>
</div>
);
}
// 组件挂载完毕时候调用
componentDidMount() {
console.log("挂载 第四步 ---> componentDidMount");
}
// 组件将要卸载时候调用
componentWillUnmount() {
console.log("挂载 第五步 ---> componentWillUnmount");
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test1"));
</script>
</body>
</html>
7-8.生命周期-getDerivedStateFromProps(新)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/17/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/17/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 所有带 will 的钩子函数都需要加上 UNSAFE_
// 1. 创建函数式组件
class MyComponent extends React.Component {
// 构造器 (第一步)
constructor(props) {
super(props);
// 初始化状态
this.state = { count: 0 };
console.log("挂载 第一步 ---> constructor");
}
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById("test1"));
};
// 如果State的任何值都取决于Props,那么就可以使用这个,但是非必须使用
// 会在调用 render 方法之前调用,
// 即在渲染 DOM 元素之前会调用,并且在初始挂载及后续更新时都会被调用.
static getDerivedStateFromProps(props, state) {
console.log("props", props); // {count: 199}
console.log("state", state); // {count: 0}
console.log("挂载 第二步 ---> getDerivedStateFromProps");
// 每次更新也会走到这里, 那么每次都会return这个数据, 则页面的数据一直不会改变
// 都会展示 Props 的值
return props; // 返回 State 则会影响 State
}
// 初始化渲染, 状态更新之后
render() {
console.log("挂载 第三步 ---> render");
return (
<div>
<h2>当前求和为: {this.state.count}</h2>
<button onClick={this.death}>卸载组件</button>
</div>
);
}
// 组件挂载完毕时候调用
componentDidMount() {
console.log("挂载 第四步 ---> componentDidMount");
}
// 组件将要卸载时候调用
componentWillUnmount() {
console.log("挂载 第五步 ---> componentWillUnmount");
}
}
// 2.渲染组件到页面
ReactDOM.render(
<MyComponent count={199} />,
document.getElementById("test1")
);
</script>
</body>
</html>
7-9.生命周期-getSnapshotBeforeUpdate(新)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/17/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/17/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 所有带 will 的钩子函数都需要加上 UNSAFE_
// 1. 创建函数式组件
class MyComponent extends React.Component {
// 构造器 (第一步)
constructor(props) {
super(props);
// 初始化状态
this.state = { count: 0 };
console.log("挂载 第一步 ---> constructor");
}
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById("test1"));
};
update = () => {
this.setState({ count: 1 });
};
/**
* getSnapshotBeforeUpdate() 方法在最近一次渲染输出(提交到 DOM 节点)之前调用.
* 在 getSnapshotBeforeUpdate() 方法中,我们可以访问更新前的 props 和 state.
* getSnapshotBeforeUpdate() 方法需要与 componentDidUpdate() 方法一起使用,否则会出现错误.
*
* 组件更新完成前做一些操作
*/
getSnapshotBeforeUpdate() {
console.log("更新 第二步 ---> getSnapshotBeforeUpdate");
return "getSnapshotBeforeUpdate";
}
// 初始化渲染, 状态更新之后
render() {
console.log("挂载 第三步 ---> render");
console.log("更新 第一步 ---> getSnapshotBeforeUpdate");
return (
<div>
<h2>当前求和为: {this.state.count}</h2>
<button onClick={this.death}>卸载组件</button>
<button onClick={this.update}>更新数据</button>
</div>
);
}
// 组件挂载完毕时候调用
componentDidUpdate(preProps, preState, snapValue) {
// 这俩哥参数都是修改之前的
console.log(preProps, preState); // {count: 199} {count: 0}
// 这个是 上个周期 getSnapshotBeforeUpdate 传过来的 snapValue
console.log("getSnapshotBeforeUpdate传过来的数据--->", snapValue); // getSnapshotBeforeUpdate
console.log("更新 第三步 ---> componentDidUpdate");
}
// 组件挂载完毕时候调用
componentDidMount() {
console.log("挂载 第四步 ---> componentDidMount");
}
// 组件将要卸载时候调用
componentWillUnmount() {
console.log("挂载 第五步 ---> componentWillUnmount");
}
}
// 2.渲染组件到页面
ReactDOM.render(
<MyComponent count={199} />,
document.getElementById("test1")
);
</script>
</body>
</html>
7-10.getSnapshotBeforeUpdate 使用场景
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
<style>
.list {
width: 200px;
height: 150px;
background-color: yellow;
overflow: auto;
}
.news {
height: 30px;
}
</style>
</head>
<body>
<!-- 准备好容器 -->
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/17/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/17/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
// 所有带 will 的钩子函数都需要加上 UNSAFE_
// 1. 创建函数式组件
class MyComponent extends React.Component {
// 构造器 (第一步)
constructor(props) {
super(props);
// 初始化状态
this.state = { newsArr: [] };
}
componentDidMount() {
setInterval(() => {
const { newsArr } = this.state;
const news = "新闻" + (newsArr.length + 1);
this.setState({ newsArr: [news, ...newsArr] });
}, 1000);
}
getSnapshotBeforeUpdate() {
return this.refs.list.scrollHeight;
}
// 初始化渲染, 状态更新之后
render() {
return (
<div className="list" ref="list">
{this.state.newsArr.map((el) => {
return (
<div key={el} className="news">
{el}
</div>
);
})}
</div>
);
}
// 组件挂载完毕时候调用
componentDidUpdate(preProps, preState, height) {
this.refs.list.scrollTop += this.refs.list.scrollHeight - height;
}
}
// 2.渲染组件到页面
ReactDOM.render(
<MyComponent count={199} />,
document.getElementById("test1")
);
</script>
</body>
</html>
7-11.生命周期总结(新)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01-函数式组件</title>
</head>
<body>
<!-- 准备好容器 -->
<div id="test1"></div>
<!-- 引入React核心库. -->
<script src="../React-js/17/react.development.js"></script>
<!-- 引入React-dom,用于支持操作DOM -->
<script src="../React-js/17/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../React-js/babel.min.js"></script>
<!-- 写这个type的意义是为了让他知道我写的是jsx -->
<script type="text/babel">
/**
* 常用:
* 1. componentDidMount() 一般做一些初始化的事儿,例如开始定制器或者发送网络请求或者订阅消息
* 2. componentWillUnmount() 一般做一些收尾的事儿,例如取消定时器
*
* 1. 初始化阶段: 由 ReactDOM.render() 触发---初次渲染
* 1. constructor()
* 2. getDerivedStateFromProps()
* 3. render()
* 4. componentDidMount()
* 2. 更新阶段: 由组件内部 setState() 或者父组件 render() 触发
* 1. getDerivedStateFromProps()
* 2. shouldComponentUpdate()
* 3. render()
* 4. getSnapshotBeforeUpdate()
* 4. componentWillUpdate()
* 3. 卸载组件: 由 ReactDOM.unmountComponentAtNode() 触发
* 1. componentWillUnmount()
*/
// 所有带 will 的钩子函数都需要加上 UNSAFE_
// 1. 创建函数式组件
class MyComponent extends React.Component {
// 构造器 (第一步)
constructor(props) {
super(props);
// 初始化状态
this.state = { count: 0 };
console.log("挂载 第一步 ---> constructor");
}
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById("test1"));
};
update = () => {
this.setState({ count: 1 });
};
/**
* getSnapshotBeforeUpdate() 方法在最近一次渲染输出(提交到 DOM 节点)之前调用.
* 在 getSnapshotBeforeUpdate() 方法中,我们可以访问更新前的 props 和 state.
* getSnapshotBeforeUpdate() 方法需要与 componentDidUpdate() 方法一起使用,否则会出现错误.
*
* 组件更新完成前做一些操作
*/
getSnapshotBeforeUpdate() {
console.log("更新 第二步 ---> getSnapshotBeforeUpdate");
return "getSnapshotBeforeUpdate";
}
// 初始化渲染, 状态更新之后
render() {
console.log("挂载 第三步 ---> render");
console.log("更新 第一步 ---> getSnapshotBeforeUpdate");
return (
<div>
<h2>当前求和为: {this.state.count}</h2>
<button onClick={this.death}>卸载组件</button>
<button onClick={this.update}>更新数据</button>
</div>
);
}
// 组件挂载完毕时候调用
componentDidUpdate(preProps, preState, snapValue) {
// 这俩哥参数都是修改之前的
console.log(preProps, preState); // {count: 199} {count: 0}
// 这个是 上个周期 getSnapshotBeforeUpdate 传过来的 snapValue
console.log("getSnapshotBeforeUpdate传过来的数据--->", snapValue); // getSnapshotBeforeUpdate
console.log("更新 第三步 ---> componentDidUpdate");
}
// 组件挂载完毕时候调用
componentDidMount() {
console.log("挂载 第四步 ---> componentDidMount");
}
// 组件将要卸载时候调用
componentWillUnmount() {
console.log("挂载 第五步 ---> componentWillUnmount");
}
}
// 2.渲染组件到页面
ReactDOM.render(
<MyComponent count={199} />,
document.getElementById("test1")
);
</script>
</body>
</html>