1、react特点
1.声明式
2.基于组件
3.随处可用
2、react安装
安装命令:npm i react react-dom
3、创建react元素
const title = React.createElement('h1',null,'Hello')
三个参数分别是:元素名称、元素属性、元素的子节点
4、渲染React元素
ReactDom.render(title,document.getElementById('root')
两个参数分别是:要渲染的React元素、挂载点
5、React脚手架
初始化项目:npx create-react-app 项目名称
启动项目:npm start
6、JSX简介
JSX是javascript XML的简写,表示在javascript 代码中写XML格式的代码。
// 导入Reactt
import React from 'react'
import ReactDOM from 'react-dom'
// 使用JSX创建React元素
const title = (
<div>JSX语法</div>
)
// 渲染React元素
ReactDOM.render(title,document.getElementById('root'))
7、脚手架中为什么可以使用JSX语法?
1.JSX不是标准的ECMAScript语法,他是ECMAScript的语法扩展。
2.需要使用babel编译处理后,才能在浏览器环境中使用。
3.create-react-app脚手架已经默认有该配置,无需手动配置。
4.编译JSX语法的包为:@babel/preset-react。
8、JSX的注意点
特殊属性名:class === className、for === htmlFor
JSX尽量使用()包裹,避免混乱。
javascript表达式插值在这里使用一个 {}
9、JSX条件渲染
10、JSX列表渲染
11、JSX样式处理
12、函数组件
使用JS中的函数创建的组件叫做:函数组件。
函数组件必须有返回值。组件名称必须以大写字母开头。使用函数名作为组件标签名。
import React from 'react'
import ReactDOM from 'react-dom'
// 用函数创建的就是函数组件
function Hello() {
return <div>函数组件</div>
}
// 渲染React元素
ReactDOM.render(<Hello/>,document.getElementById('root'))
13、类组件
使用ES6的class创建的组件叫做类组件
类组件名称也必须以大写字母开头。类组件应该继承ReactComponent父类,从而可以使用父类中提供的方法或属性。类组件必须提供render()方法。render()方法必须有返回值,表示该组件的结构。
class Hello extends React.Component{
render(){
return <div>Hello </div>
}
}
ReactDom.render(<Hello />,root)
14、将组件抽离为独立JS文件
1.创建JS文件
2.在JS文件中导入React
3.创建组件(函数 或 类)
4.在JS文件中导出该组件
5.在index.js中导入Hello组件
6.渲染组件
15、事件绑定
语法:on + 事件名称 = {事件处理程序}
// 1.类组件事件绑定
class Hello extends React.Component {
doclick(){
console.log('点击事件');
}
render(){
return ( <button onClick={ this.doclick}>类组件</button> )
}
}
// 2.函数组件事件绑定
function Hello(){
function doclick(){
console.log('点击事件');
}
return ( <button onClick={ doclick }>函数组件</button> )
}
16、有状态组件和无状态组件
函数组件又叫做无状态组件,类组件又叫做有状态组件。
函数组件没有自己的状态,只负责数据展示。
类组件有组件的状态,负责更新UI,让页面动起来。
17、state和setState
state是定义数据
setState是修改数据。setState()作用:1.修改state。2.更新UI。思想:数据驱动视图。
class Hello extends React.Component {
// 1.ES6写法
constructor(){
super()
this.state = {
count:2
}
}
// 简写方式
state = {
count:0
}
render(){
return ( <div>计数器:{ this.state.count }</div> )
}
}
// setState修改数据
class Hello extends React.Component {
state = {
count:0
}
render(){
return (
<div>
<h1>计数器:{ this.state.count}</h1>
<button onClick={() => {
this.setState({
count: this.state.count + 1
})
}}>+1</button>
</div>
)
}
}
18、事件绑定this指向问题
// 1.可以使用箭头函数
<button onClick={ () => this.doclick()}>+1</button>
// 2.利用ES5中的bind方法,将事件处理程序中的this与组件实例绑定到一起。
constructor(){
super()
this.state = {
count:0
}
this.doclick = this.doclick.bind(this)
}
// 3.使用class的实例方法。
doclick = () =>{
this.setState({
count:this.state.count + 1
})
}
19、受控组件
受到React控制的表单元素就是受控组件
state = {
txt:''
}
<input type="text" value={this.state.txt} />
20、表单处理
class Hello extends React.Component {
state = {
txt: '',
content:'',
city:'',
isChecked:false
}
// 文本框事件处理程序
dochange = e => {
this.setState({
txt: e.target.value
})
}
// 富文本事件处理程序
dochange2 = e => {
this.setState({
content:e.target.value
})
}
// 下拉框事件处理程序
dochange3 = e => {
this.setState({
city:e.target.value
})
}
// 复选框事件处理程序
dochange4 = e => {
this.setState({
isChecked:e.target.checked
})
}
render(){
return (
<div>
{/* 文本框 */}
<input type="text" value={ this.state.txt } onChange={ this.dochange }></input>
<br/>
{/* 富文本 */}
<textarea value={ this.state.content } onChange={ this.dochange2 }></textarea>
<br/>
{/* 下拉框 */}
<select value={ this.state.city} onChange={ this.dochange3}>
<option value='sh'>上海</option>
<option value='bj'>北京</option>
<option value='gz'>广州</option>
</select>
<br/>
{/* 复选框 */}
<input type="checkbox" checked={this.state.isChecked} onChange={this.dochange4}></input>
</div>
)
}
}
21、多表单事件处理程序优化
class Hello extends React.Component {
state = {
txt: '',
content:'',
city:'',
isChecked:false
}
dochange = e => {
// 1.获取当前DOM对象
const target = e.target
// 2.根据表单元素类型获取值
const value = target.type === 'checkbox'
? target.checked
: target.value
// 3.获取name
const name = target.name
this.setState({
[name]: value
})
}
render(){
return (
<div>
{/* 文本框 */}
<input name='txt' type="text" value={ this.state.txt } onChange={ this.dochange }></input>
<br/>
{/* 富文本 */}
<textarea name='content' value={ this.state.content } onChange={ this.dochange }></textarea>
<br/>
{/* 下拉框 */}
<select name='city' value={ this.state.city} onChange={ this.dochange}>
<option value='sh'>上海</option>
<option value='bj'>北京</option>
<option value='gz'>广州</option>
</select>
<br/>
{/* 复选框 */}
<input name='isChecked' type="checkbox" checked={this.state.isChecked} onChange={this.dochange}></input>
</div>
)
}
}
22、非受控组件
class Hello extends React.Component {
constructor(){
super()
// 1.创建ref
this.txtRef = React.createRef()
}
// 3.获取文本框的值
getTxt = () => {
console.log(this.txtRef.current.value);
}
render(){
return (
<div>
{/* 2.绑定Ref */}
<input type="text" ref={ this.txtRef}></input>
<button onClick={ this.getTxt }>获取文本框的值</button>
</div>
)
}
}
23、组件的props
props是一个对象。函数组件通过props.name获取。类组件通过this.props.name获取。
// 函数组件
const Hello = props => {
return (
<div>props:{props.name}</div>
)
}
// 类组件
class Hello extends React.Component {
render(){
return (
<div>props:{this.props.name}</div>
)
}
}
// 渲染React元素
ReactDOM.render(<Hello name="jack"/>,document.getElementById('root'))
特点: 1.props可以给组件传递任意类型的数据
2.props是只读的对象,只能读取属性的值,无法修改对象
3.注意:使用类组件时,如果写了构造函数,应该将props传递给super(),否则,无法在构造函数中获取到props
class Hello extends React.Component {
constructor(props) {
super(props)
}
render(){
return <div>接收到的数据:{props.name}<div/>
}
}
}
24、组件通讯
父传子
1.父组件提供要传递的state数据
2.给子组件标签添加属性,值为state中的数据
3.子组件中通过props接收父组件中传递的数据
// 子组件
class Hello extends React.Component {
state = {
lastname:'王'
}
render(){
return (
<div className='box'>父组件
<Hello2 name={this.state.lastname}></Hello2>
</div>
)
}
}
// 父组件
const Hello2 = props => {
return (
<div className='box2'>子组件:{props.name}</div>
)
}
子传父
父组件定义一个回调函数,在子组件标签中调用。子组件通过props进行使用,将数据作为形参传给回调函数。
// 父组件
class Hello extends React.Component {
state = {
shuju:''
}
// 1.在父组件中定义回调函数
getChildMsg = msg => {
console.log('子组件传递过来的数据',msg);
// 4.通过setState将传递过来的数据进行修改
this.setState({
shuju:msg
})
}
render() {
return (
<div className='box'>父组件:{this.state.shuju}
{/* 2.在子组件标签中传递回调函数 */}
<Hello2 getMsg={this.getChildMsg}></Hello2>
</div>
)
}
}
// 子组件
class Hello2 extends React.Component {
state = {
msg:'你好'
}
// 3.通过props将state里的数据作为参数传给回调函数
doclick = () => {
this.props.getMsg(this.state.msg)
}
render(){
return(
<div className='box2'>子组件
<button onClick={this.doclick}>给父组件传递数据</button>
</div>
)
}
}
非父子组件
25、Context
1.如果两个组件是多层嵌套,可以使用Context实现组件通讯
2.Context提供了两个组件:Provider和Consumer
3.Provider组件:用来提供数据
4.Consumer组件:用来消费数据
// 1.调用React.createContext()创建Provider和Consumer两个组件
const { Provider,Consumer } = React.createContext()
// 2.使用Provider包裹组件,并用value传递数据
class Hello extends React.Component {
render () {
return (
<Provider value="传递的数据">
<div>组件1
<Hello2></Hello2>
</div>
</Provider>
)
}
}
// ...省略中间组件
// 3.使用Consumer包裹要接收数据的组件,并使用回调函数接收数据
class Hello4 extends React.Component {
render () {
return (
<Consumer>
{data => <div>组件4 -- {data}</div>}
</Consumer>
)
}
}
26、props的children属性
children属性:表示组件标签的子节点,当组件标签有子节点时,props就会有该属性、
children属性与普通的props一样,值可以是任意值(文本、React元素、组件、甚至是函数)
const Hello = props => {
console.log(props);
return(
<div>peops的children属性:
{props.children}
</div>
)
}
// 渲染React元素
ReactDOM.render(<Hello>子节点</Hello>,document.getElementById('root'))
27、props校验
1.安装包 prop-types(yarn add prop-types/npm i props-types)
2.导入 prop-types包
3.使用组件名.propTypes = {} 给组件的props添加校验规则
// 2.导入props-types
import PropTypes from 'prop-types';
const Hello = props => {
console.log(props);
return(
<div>
{props.colors}
</div>
)
// 3.添加校验规则
Hello.PropTypes = {
colors:PropTypes.array
}
}
// 渲染React元素
ReactDOM.render(<Hello colors={19}></Hello>,document.getElementById('root'))
- 常见类型:array、bool、func、number、object、string
- React元素类型:element
- 必填项:isRequired
- 特定结构的对象:shape({})
28、props的默认值
const Hello = props => {
return (
<div>
{props.pageSize}
</div>
)
}
// 给props添加默认值
Hello.defaultProps = {
pageSize:10
}
// 给props设置默认值时,在未传入props时生效
ReactDOM.render(<Hello />,document.getElementById('root'))
29、组件的生命周期
创建时
constructor 创建组件时最先执行
render 每次组件渲染都会触发
componenDidMount 组件挂载后
更新时
render 在更新阶段的执行时机:1.setState()2.forceUpdate()3.组件接收到新的props时
componentDidUpdate 组件更新后 注意:如果要setState()必须放在一个if条件中
卸载时
componentwillUnmount 组件卸载
30、render props模式
1.封装复用的状态逻辑代码(状态,和操作状态的方法)
2.在render中使用props.render将状态暴露出去
3.调用组件的时候使用render将组件作为形参,使用返回值来渲染UI结构