react总结

76 阅读7分钟

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条件渲染

image.png

10、JSX列表渲染

image.png

11、JSX样式处理

image.png

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>
    )
 }
}

非父子组件

image.png

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、组件的生命周期

image.png

创建时

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结构