文章目录
前言
自己整理的react文档,结合官网和所学知识的一个总结希望对各位有用。话不多说看下文:
一、React简介
1. React是什么
2. react 与 vue 最大的区别就是:
在表层上,模板的语法不同,React是通过JSX渲染模板。. 而Vue是通过一种拓展的HTML语法进行渲染,但其实这只是表面现象,毕竟React并不必须依赖JSX。. 在深层上,模板的原理不同,这才是他们的本质区别:React是在组件JS代码中,通过原生JS实现模板中的常见语法,比如插值,条件,循环等,都是通过JS语法实现的,更加纯粹更加原生。. 而Vue是在和组件JS代码分离的单独的模板中,通过指令来实现的,比如条件语句就需要 v-if 来实现对这一点,这样的做法显得有些独特,会把HTML弄得很乱。
3. React特点
4. React介绍描述
1.用于动态构建用户界面的 JavaScript 库(只关注于视图)
2.由Facebook开源
5. React高效的原因
1.使用虚拟(virtual)DOM, 不总是直接操作页面真实DOM。
2.DOM Diffing算法, 最小化页面重绘。
关于虚拟DOM:
1.本质上是object类型的对象(一般对象)
2.虚拟DOM比较轻,真实DOM比较重。因为虚拟DOM
6.React强大之处
速度快
它并不直接对DOM进行操作,引入了一个叫做虚拟DOM的概念,安插在javascript逻辑和实际的DOM之间,性能好
很好的跨浏览器兼容
虚拟DOM帮助我们解决了跨浏览器问题,它为我们提供了标准化的API,甚至在IE8中都是没问题的。
所有都是component:
组件化的代码更加模块化,重用代码更容易,可维护性高。
单向数据流
Flux是一个用于在JavaScript应用中创建单向数据层的架构,它随着React视图库的开发而被Facebook概念化。
兼容性好
比如使用RequireJS来加载和打包,而Browserify和Webpack适用于构建大型应用。它们使得那些艰难的任务不再让人望而生畏
二、React基础格式
<!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>Document</title>
</head>
<body>
<div id="test"></div>
<!-- 引入 react 核心库 -->
<script src="./js/react.development.js"></script>
<!-- 引入 react-dom 用于支持忍让传统操作dom -->
<script src="./js/react-dom.development.js"></script>
<!-- 引入 babel
1.es6 ==> es5
2.jsx ==>js -->
<script src="./js/babel.min.js"></script>
<script type="text/babel">
// 1.创建虚拟 dom
const VDOM = <h1>hello word</h1>
// 2.渲染到页面中的指定dom
// ReactDOM.render(虚拟dom,真实dom)
ReactDOM.render(VDOM,document.getElementById('test'))
</script>
</body>
</html>
讲解: 首先我们需要完成基础引入react。然后先创建一个虚拟dom再把虚拟dom在指定元素里渲染成真实dom
1.什么是虚拟dom?
什么是虚拟 DOM? 在 React 中,render 执行的结果得到的并不是真正的 DOM 节点,结果仅仅是轻量级的 JavaScript 对象,我们称之为 virtual DOM。 虚拟 DOM 是 React 的一大亮点,具有 batching (批处理) 和高效的 Diff 算法。
2.为什么要创建虚拟dom?
我们知道,虚拟DOM的概念是由Facebook的React团队最早提出来的,也是React框架的核心概念之一。 它的作用是以js的形式在内存中描述真实的DOM结构,这样当页面内容需要发生变动时,React可以通过对前后虚拟DOM的比对,计算出如何以最小的代价操作真实DOM。
三、React也分为俩种创建方式
1. 使用js的方式来创建
声明 不建议使用 。 代码多
<!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>Document</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入 react 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持忍让传统操作dom -->
<script src="../js/react-dom.development.js"></script>
<script type="text/javascript">
// 1.创建虚拟 dom
// const VDOM = React.createElement(标签名,标签属性,标签内容)
const VDOM = React.createElement('h1', { id: "title" }, React.createElement('span',{},"hello react"))
// 2.渲染到页面中的指定dom
// ReactDOM.render(虚拟dom,真实dom)
ReactDOM.render(VDOM, document.getElementById('test'));
</script>
</body>
</html>
2.使用jsx方式创建
声明 建议使用 它会自动转换成js格式 代码简洁(它没有this指向 需要自己绑定this或者使用箭头函数)
<!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>Document</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入 react 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持忍让传统操作dom -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入 babel
1.es6 ==> es5
2.jsx ==>js -->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建虚拟 dom
// const VDOM = React.createElement(标签名,标签属性,标签内容)
const VDOM = (
<h1>hello
<span>react-dom</span>
</h1>
)
// 2.渲染到页面中的指定dom
// ReactDOM.render(虚拟dom,真实dom)
ReactDOM.render(VDOM, document.getElementById('test'));
</script>
</body>
</html>
四、jsx的语法规则
<!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>Document</title>
<style>
.title{
color: aliceblue;
}
</style>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入 react 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持忍让传统操作dom -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入 babel
1.es6 ==> es5
2.jsx ==>js -->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
let myData = 'Student';
let idData = 'zhongwu';
// 1.创建虚拟 dom
// const VDOM = React.createElement(标签名,标签属性,标签内容)
const VDOM = (
<div>
<h1 className="title" id={idData}>
hello,
<span>{ myData }</span>
<input type="text"></input>
<Good />
</h1>
</div>
)
// 2.渲染到页面中的指定dom
// ReactDOM.render(虚拟dom,真实dom)
ReactDOM.render(VDOM,document.getElementById('test'));
</script>
</body>
</html>
注意:
jsx的语法规则:
1.定义虚拟dom时,不要用引号;
2.标签中混入js表达式时,要用{}
3.样式的类名指定不要用class要用className;
4.内联样式,要用style={{key:value}}的形式去写
5.只能有一个根元素
6所有标签都必须要闭合
7. 标签的首字母:
1.若是小写字母开头,则将改标签转化为html同名的元素,渲染到页面
若html没有同名的元素,则报错
2.若大写字母开头,react就会去渲染对应的组件,若组件没有定义,则报错;
/
五、react定义组件
**声明:**组件化是React的核心思想,也是我们后续课程的重点,前面我们封装的App本身就是一个组件: 组件化提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。 任何的应用都会被抽象成一颗组件树。 有了组件化的思想,我们在之后的开发中就要充分的利用它。 尽可能的将页面拆分成一个个小的、可复用的组件。 这样让我们的代码更加方便组织和管理,并且扩展性也更强。 React的组件相对于Vue更加的灵活和多样,按照不同的方式可以分成很多类组件: 这些概念有很多重叠,但是他们最主要是关注数据逻辑和UI展示的分离: 当然还有很多组件的其他概念:比如异步组件、高阶组件等,我们后续再学习。
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>Document</title>
<style>
.title {
color: aliceblue;
}
</style>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入 react 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持忍让传统操作dom -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入 babel
1.es6 ==> es5
2.jsx ==>js -->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建函数式组件
function MyComponent() {
console.log(this)//undefined ,因为babel编译,开启了严格模式
// 一定需要有返回值
return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2>
}
// 2.渲染到页面中的指定dom
// ReactDOM.render(虚拟dom,真实dom)
ReactDOM.render(<MyComponent />, document.getElementById('test'));
/*
执行ReactDOM.render()方法之后,发生了什么?
1.React解析了组件标签,找到了对应的组件
2.发现这个组件是一个函数定义的 随后调用改函数,生成了一个虚拟dom
3.最后将虚拟dom转化为真实dom,呈现在页面中
*/
</script>
</body>
</html>
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>Document</title>
<style>
</style>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入 react 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持忍让传统操作dom -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入 babel
1.es6 ==> es5
2.jsx ==>js -->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建一个 类式组件
class MyComponent extends React.Component{
//render方法是放在原型上
// render中的this是谁? ---实例对象
render(){
console.log('render中的this',this)
return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
}
}
ReactDOM.render(<MyComponent />, document.getElementById('test'));
/*
执行ReactDOM.render()方法之后,发生了什么?
1.React解析了组件标签,找到了对应的组件
2.发现这个组件是一个类定义的 随后new出来一个实例对象并通过该实例对象调用原型上的render方法
3.最将render() 返回的内容生成一个虚拟dom
4.最后将虚拟dom转化为真实dom,呈现在页面中
*/
let c = new MyComponent();
console.log(c)
</script>
</body>
</html>
3.函数式组件和类式组件的区别
1、函数组件是一个纯函数,它接收一个props对象返回一个react元素;而类组件需要去继承React.Component并且创建render函数返回react元素。
2、函数组件没有生命周期和状态state,而类组件有。
3、 官方建议使用函数式组件
六、 组件实例的三大属性
1.state
声明:
状态( state )即数据,是组件内部的私有数据,只能在组件内部使用
state的值是对象,表示一个组件中可以有多个数据
通过 this.state 来获取状态
通过setState修改state数据(注意:state的数据是 只读 的不能修改。想要修改的话用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>Document</title>
<style>
</style>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入 react 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持忍让传统操作dom -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入 babel
1.es6 ==> es5
2.jsx ==>js -->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建一个 类式组件
class Weather extends React.Component {
state = { isTian: true, wind: '微风' };
render() {
let { isTian, wind } = this.state;
return <h2 onClick={this.changewWeather}>今天天气很爽 {isTian ? "不冷" : "不热"},{wind}</h2> //istian
}
changewWeather = () => {
let { isTian } = this.state;
this.setState({ isTian: !isTian })//这里的修改,是覆盖还是合并?
}
}
ReactDOM.render(<Weather />, document.getElementById('test'));
</script>
</body>
</html>
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>Document</title>
</head>
<style>
.title {
color: aqua;
}
</style>
<body>
<div id="test">
</div>
<div id="test1">
</div>
<div id="test2">
</div>
<!-- 引入React核心库 -->
<script src="../js/react.development.js"></script>
<!-- 操作dom -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel ES6==>ES5 JSX==>JS -->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
class Weather extends React.Component {
constructor(props) {//是否接受,取决于是否使用外部数据
super(props)//只能上面接受了props,super()就去传递,否则后续的使用,可能就会出现问题
}
static propTypes = {
name: PropTypes.string.isRequired,//限制name为字符串类型,必填
// age: PropTypes.number,
sex: PropTypes.string,
speak: PropTypes.func
}
static defaultProps = {
sex: '男',
}
render() {
let { name, age, sex } = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age + 1}</li>
</ul>
)
}
}
/*
问题:
1.数据类型是否有对应的限制?
2.数据的数量 批量传输可以使用展开运算符
*/
ReactDOM.render(<Weather name="tom" age={26} sex="女" />, document.getElementById('test'))
</script>
</body>
</html>
3、ref
**声明:**在典型的 React 数据流中,props 是父组件与子组件交互的唯一方式。要修改一个子组件,你需要使用新的 props 来重新渲染它。但是,在某些情况下,你需要在典型数据流之外强制修改子组件。被修改的子组件可能是一个 React 组件的实例,也可能是一个 DOM 元素。对于这两种情况,React 提供了使用ref来解决它。
作者:智慧女孩要秃头
链接:https://juejin.cn/post/7047113456993959972
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
<!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>ref</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入 React 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持 react 操作 DOM -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel:
1. ES6 ==> ES5
2. jsx ==> js
-->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
class Person extends React.Component {
showData = () => {
//转款专用:每一个ref都是唯一的,存在this.refs中
let { ipt } = this.refs;
alert(ipt.value)
}
getData=()=>{
let { ipt1 } = this.refs;
alert(ipt1.value)
}
render() {
return (
<div>
<input ref='ipt' type="text" placeholder="请输入数量" />
<button onClick={this.showData}>点我提示左侧的数据</button>
<input onClick={this.getData} ref='ipt1' type="text" placeholder="请输入数量" />
</div>
)
}
}
ReactDOM.render(<Person />, document.getElementById('test'))
</script>
</body>
</html>
七 、事件处理
声明: 1.通过onXxx属性指定事件处理函数(注意大小写)
1)React使用的是自定义(合成)事件, 而不是使用的原生DOM事件 —为了更好的兼容性
2)React中的事件是通过事件委托方式处理的(委托给组件最外层的元素) —为了更加高效
2.通过event.target得到发生事件的DOM元素对象 — 勿过度使用 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>ref</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<!-- 引入 React 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持 react 操作 DOM -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel:
1. ES6 ==> ES5
2. jsx ==> js
-->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
class Person extends React.Component {
myRef = React.createRef(); //容量为1,只能存一个,多余会覆盖前者
myRef1 = React.createRef();
showData = (event) => {
alert(this.myRef.current.value)
console.log(event.target)
}
showData1 = () => {
alert(this.myRef1.current.value)
}
// 回调函数
// 1.自己写的函数
// 2.不是自己调用的
// 3.这个函数最后执行了
render() {
return (
<div>
{/* 这里是jsx注释 */}
<input ref={this.myRef} type="text" placeholder="请输入数量" />
<button onClick={this.showData}>点我提示左侧的数据</button>
<input onBlur={this.showData1} ref={this.myRef1} type="text" placeholder="请输入数量" />
</div>
)
}
}
ReactDOM.render(<Person />, document.getElementById('test'))
</script>
</body>
</html>
八、react收集表单
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>ref</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入 React 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持 react 操作 DOM -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel:
1. ES6 ==> ES5
2. jsx ==> js
-->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
class Person extends React.Component {
handler=(event)=>{
event.preventDefault();//阻止默认事件 --- 阻止表单跳转
let {username,password} = this;
alert(`你输入的名字${username.value},密码是${password.value}`)
}
render() {
return (
<div>
<form action="https://www.baidu.com" onSubmit={this.handler}>
用户名:<input type="text" name='username' ref={ c =>this.username=c} />
密码:<input type="text" name="password" ref={ c =>this.password=c } />
<button type="submit">登录</button>
</form>
</div>
)
}
}
ReactDOM.render(<Person />, document.getElementById('test'))
</script>
</body>
</html>
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>ref</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入 React 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持 react 操作 DOM -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel:
1. ES6 ==> ES5
2. jsx ==> js
-->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
//受控组件
class Person extends React.Component {
//初始化状态
state = {
username: '',//用户名
password: ''//密码
}
//保存用户名到状态中
saveUsername = (event) => {
this.setState({ username: event.target.value })
}
//保存密码到状态中
savePassword = (event) => {
this.setState({ password: event.target.value })
}
//表单提交回调
handler = (event) => {
event.preventDefault();//阻止默认事件 --- 阻止表单跳转
let { username, password } = this.state;
alert(`你输入的名字${username},密码是${password}`)
}
render() {
return (
<div>
<form action="https://www.baidu.com" onSubmit={this.handler}>
用户名:<input type="text" name='username' onChange={this.saveUsername} />
密码:<input type="text" name="password" onChange={this.savePassword} />
<button type="submit">登录</button>
</form>
</div>
)
}
}
ReactDOM.render(<Person />, document.getElementById('test'))
</script>
</body>
</html>
九、高阶函数
1.高阶函数
声明:
高阶函数:如果一个函数符合下面2个规范中的任何一个,那么它就是属于一个高阶函数
1.若A函数,接受的参数是一个函数,那么A就可以称为高阶函数
2.若A函数,调用的返回值依然是一个函数,那么A也可以称为高阶函数
常见的高阶函数:Promise,setTimeout,arr.map回调函数等等
函数柯里化:通过函数的继续调用 返回值为函数的方式,实现的多次接收参数,最会统一处理的函数编码形式
<!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>ref</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入 React 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持 react 操作 DOM -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel:
1. ES6 ==> ES5
2. jsx ==> js
-->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
region
function sum(a){
return (b)=>{
return (c)=>{
return a+b+c;
}
}
}
*/
//受控组件
class Person extends React.Component {
//初始化状态
state = {
username: '',//用户名
password: ''//密码
}
//保存用户名到状态中
saveUsername = (event) => {
this.setState({ username: event.target.value })
}
//保存密码到状态中
savePassword = (event) => {
this.setState({ password: event.target.value })
}
//保存表单数据到状态中
saveFormData = (dataType) => {//这里传来的是标识 标识当前标签
return (event)=>{ //这里的回调谁执行?? input标签的 onchange事件
// console.log(event.target.value,'@@@')
this.setState({
[dataType]: event.target.value
})
// console.log(dataType) // username password
}
}
//表单提交回调
handler = (event) => {
event.preventDefault();//阻止默认事件 --- 阻止表单跳转
let { username, password } = this.state;
alert(`你输入的名字${username},密码是${password}`)
}
render() {
return (
<div>
<form action="https://www.baidu.com" onSubmit={this.handler}>
用户名:<input type="text" name='username' onChange={this.saveFormData('username')} />
密码:<input type="text" name="password" onChange={this.saveFormData('password')} />
<button type="submit">登录</button>
</form>
</div>
)
}
}
ReactDOM.render(<Person />, document.getElementById('test'))
</script>
</body>
</html>
2.函数柯里化
声明:
柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术
<!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>ref</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入 React 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持 react 操作 DOM -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel:
1. ES6 ==> ES5
2. jsx ==> js
-->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
//受控组件
class Person extends React.Component {
//初始化状态
state = {
username: '',//用户名
password: ''//密码
}
//保存用户名到状态中
saveUsername = (event) => {
this.setState({ username: event.target.value })
}
//保存密码到状态中
savePassword = (event) => {
this.setState({ password: event.target.value })
}
//保存表单数据到状态中
saveFormData = (dataType, event) => {//这里传来的是标识 标识当前标签
this.setState({
[dataType]: event.target.value
})
}
//表单提交回调
handler = (event) => {
event.preventDefault();//阻止默认事件 --- 阻止表单跳转
let { username, password } = this.state;
alert(`你输入的名字${username},密码是${password}`)
}
render() {
return (
<div>
<form action="https://www.baidu.com" onSubmit={this.handler}>
用户名:<input type="text" name='username' onChange={event => this.saveFormData('username', event)} />
密码:<input type="text" name="password" onChange={event => this.saveFormData('password', event)} />
<button type="submit">登录</button>
</form>
</div>
)
}
}
ReactDOM.render(<Person />, document.getElementById('test'))
</script>
</body>
</html>
十、 组件的生命周期
1.什么是组件的生命周期:
组件从被创建到挂载到页面中运行,再到组件不用时卸载的过程
2.钩子函数的作用:
为开发人员在不同阶段操作组件提供了时机。
3.生命周期的意义:
有助于理解组件的运行方式
完成更复杂的组件功能
分析组件错误原因等
4.生命周期使用场景
<!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>ref</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入 React 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持 react 操作 DOM -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel:
1. ES6 ==> ES5
2. jsx ==> js
-->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建虚拟 dom
// 1. 生命周期回调函数 === 生命周期钩子函数 === 生命周期函数 === 生命周期钩子
class Person extends React.Component {
state = {
opacity: 1
}
constructor(){
super();
console.log('constructor')
}
//组件将要挂载
componentWillMount(){
console.log("componentWillMount")
}
//组件将要卸载
componentWillUnmount(){
console.log("啊 我Neo写咋")
clearInterval(this.timer)
}
//组件挂载完成之后
componentDidMount() {
console.log("componentDidMount")
setInterval(() => {
// 获取原状态
let { opacity } = this.state;
opacity -= 0.1;
if (opacity <= 0) opacity = 1;
//设置新透明度
this.setState({ opacity });
}, 200)
}
death=()=>{
//卸载组件
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
render() {
console.log("render")
return (
<div>
<span style={{ opacity: this.state.opacity } } >学不会React怎么办</span>
<button onClick={this.death}>按钮</button>
</div>
)
}
}
// 2.渲染到页面中的指定dom
ReactDOM.render(<Person />, document.getElementById('test'))
</script>
</body>
</html>
5.react 生命周期(旧)
生命周期的三个阶段(旧)
1. 初始化阶段: 由ReactDOM.render()触发—初次渲染
1.constructor()
2.componentWillMount()
3.render()
4.componentDidMount()
2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
1.shouldComponentUpdate()
2.componentWillUpdate()
3.render()
4.componentDidUpdate()
3. 卸载组件: 由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>ref</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入 React 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持 react 操作 DOM -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel:
1. ES6 ==> ES5
2. jsx ==> js
-->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
1.constructor()
2.componentWillMount()
3.render()
4.componentDidMount() === >常用:
一般在这个钩子中做一些初始化的事情:例如:开启定时器,发送网络请求
2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
1.shouldComponentUpdate()
2.componentWillUpdate()
3.render() ===》必须使用
4.componentDidUpdate()
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
1.componentWillUnmount() ===》常用
一般在中国函数中做一些收尾的事,例如:关闭定时器 取消订阅
*/
class Person extends React.Component {
state = { count: 0 }
// 点我
add = () => {
//获取原状态
let { count } = this.state;
// 更新状态
this.setState({ count: count + 1 });
}
// 卸载组件
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
force = () => {
this.forceUpdate()
}
// 数据更新的 '阀门'
shouldComponentUpdate = () => {
console.log("count ------ shouldComponentUpdate")
return true; //这里必须有返回值,其次返回值默认为true
}
// 组件将要更新的钩子
componentWillUpdate() {
console.log("count ---- componentWillUpdate")
}
// 组件更新完毕的钩子
componentDidUpdate() {
console.log("count ---- componentDidMount")
}
render() {
return (
<div>
<h2>当前求和为:{this.state.count}</h2>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载组件</button>
<button onClick={this.force}>不更改任何状态中的数据,强制更新</button>
</div>
)
}
}
// 父组件
class A extends React.Component {
state = { carName: "电动车" }
changeCar = () => {
this.setState({ carName: '飞机' });
}
render() {
console.log("render")
return (
<div>
<span>我是a组件</span>
<button onClick={this.changeCar}>换车</button>
<B carName={this.state.carName} />
</div>
)
}
}
// 子组件
class B extends A {
//组件将要接收新的props 的钩子
componentWillReceiveProps() {
console.log("B ---- componentWillReceiveProps ")
}
// 数据更新的 '阀门'
shouldComponentUpdate = () => {
console.log("count ------ shouldComponentUpdate")
return true; //这里必须有返回值,其次返回值默认为true
}
// 组件将要更新的钩子
componentWillUpdate() {
console.log("count ---- componentWillUpdate")
}
// 组件更新完毕的钩子
componentDidUpdate() {
console.log("count ---- componentDidMount")
}
render() {
return (
<div>
我是b组件,接收到的车是:{this.props.carName}
</div>
)
}
}
ReactDOM.render(<A />, document.getElementById('test'))
</script>
</body>
</html>
6.React 生命周期(新)
生命周期的三个阶段(新)
- 初始化阶段: 由ReactDOM.render()触发—初次渲染
1.constructor()
2.getDerivedStateFromProps
3.render()
4.componentDidMount()
2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
1.getDerivedStateFromProps
2.shouldComponentUpdate()
3.render()
4.getSnapshotBeforeUpdate
5.componentDidUpdate()
3. 卸载组件: 由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>ref</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入 React 核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入 react-dom 用于支持 react 操作 DOM -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel:
1. ES6 ==> ES5
2. jsx ==> js
-->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
1.constructor()
2.componentWillMount()
3.render()
4.componentDidMount() === >常用:
一般在这个钩子中做一些初始化的事情:例如:开启定时器,发送网络请求
2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
1.shouldComponentUpdate()
2.componentWillUpdate()
3.render() ===》必须使用
4.componentDidUpdate()
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
1.componentWillUnmount() ===》常用
一般在中国函数中做一些收尾的事,例如:关闭定时器 取消订阅
*/
class Person extends React.Component {
state = { count: 0 }
// 点我
add = () => {
//获取原状态
let { count } = this.state;
// 更新状态
this.setState({ count: count + 1 });
}
// 卸载组件
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
force = () => {
this.forceUpdate()
}
// 数据更新的 '阀门'
shouldComponentUpdate = () => {
console.log("count ------ shouldComponentUpdate")
return true; //这里必须有返回值,其次返回值默认为true
}
// 组件将要更新的钩子
componentWillUpdate() {
console.log("count ---- componentWillUpdate")
}
// 组件更新完毕的钩子
componentDidUpdate() {
console.log("count ---- componentDidMount")
}
render() {
return (
<div>
<h2>当前求和为:{this.state.count}</h2>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载组件</button>
<button onClick={this.force}>不更改任何状态中的数据,强制更新</button>
</div>
)
}
}
// 父组件
class A extends React.Component {
state = { carName: "电动车" }
changeCar = () => {
this.setState({ carName: '飞机' });
}
static getDerivedStateFromProps(props,state){
// 这里必须要一个返回值 ==》 state or null
// 这里的state会覆盖原本的状态,并且后续也无法修改
// 能将外部的接受的props 赋值给 组件自身的 state
// 如果你希望自身的state 一直 全部依赖于外部的props,那么可以使用这个生命周期函数
return{carName:'qq'}
}
// 获取数据
getSnapshotBeforeUpDate(prevState,prevProps){
}
render() {
console.log("A --- render")
return (
<div>
<span>我是a组件</span>
<button onClick={this.changeCar}>换车</button>
<B carName={this.state.carName} />
</div>
)
}
}
// 子组件
class B extends A {
//组件将要接收新的props 的钩子
componentWillReceiveProps() {
console.log("B ---- componentWillReceiveProps ")
}
// 数据更新的 '阀门'
shouldComponentUpdate = () => {
console.log("count ------ shouldComponentUpdate")
return true; //这里必须有返回值,其次返回值默认为true
}
// 组件将要更新的钩子
componentWillUpdate() {
console.log("count ---- componentWillUpdate")
}
// 组件更新完毕的钩子
componentDidUpdate() {
console.log("count ---- componentDidMount")
}
render() {
return (
<div>
我是b组件,接收到的车是:{this.props.carName}
</div>
)
}
}
ReactDOM.render(<A />, document.getElementById('test'))
</script>
</body>
</html>
7. 重要的勾子
1.render:初始化渲染或更新渲染调用
2.componentDidMount:开启监听, 发送ajax请求
3.componentWillUnmount:做一些收尾工作, 如: 清理定时器
8. 即将废弃的勾子
1.componentWillMount
2.componentWillReceiveProps
3.componentWillUpdate
现在使用会出现警告,下一个大版本需要加上UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用。
总结
以上为react的基础知识,代码里面有注释 。下期出react脚手架。喜欢的话证明自己来过^ - ^