目录
安装
npm i -g create-react-app
安装官方脚手架create-react-app 01_react
初始化
React&ReactDOM
React只做逻辑层,reactDOM去渲染真实的DOM
将项目中src下目录的文件全部删除新增index.js,App.js
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'
ReactDOM.render(<App />,document.querySelector('#root'))
App.js
import React from "react";
class App extends React.Component{
render(){
return(
<div>react学习</div>
)
}
}
export default App;
JSX
在JavaScript中直接写的标签,是一个JSX(JS+XML,由于HTML也是XML的一种,可以认为JS+HTML)元素,也是一个react元素,这个元素实际是一个对象,就是虚拟DOM元素
React 认为渲染逻辑本质上与其他 UI 逻辑内在耦合.比如,在 UI 中需要绑定处理事件、在某些时刻状态发生变化时需要通知到 UI,以及需要在 UI 中展示准备好的数据。
元素渲染
元素是构成React应用的最小砖块,比如:
const ele = <h1>hello,world</h1>
与浏览器的 DOM 元素不同,React 元素是创建开销极小的普通对象。React DOM 会负责更新 DOM 来与 React 元素保持一致
修改状态state
import React from 'react'
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
// 声明响应式的数据
count: 0,
}
}
add() {
// console.log(this.state.count)
// 修改state必须通过setState来进行修改
// setState它是个异步函数
// this.setState({
// count: this.state.count + 1,
// })
// console.log(this.state.count)
// 函数的写法
this.setState(
(prevState, prevProps) => ({
count: prevState.count + 1,
}),
() => {
console.log(this.state.count)
}
)
}
render() {
return (
//class要写成className,style使用{{}}包裹
<div className="container" style={{ color: 'red', marginTop: 20 }}>
<h2>hello jsx</h2>
<h2>
{name}- {1 + 1}
</h2>
<hr />
<h3> 当前的值:{this.state.count}</h3>
<button onClick={() => this.add()}>+1</button>
</div>
)
}
}
export default App;
除了constructor
之外的其它地方,如果需要修改状态,都只能通过this.setState
方法
如果下一个状态依赖于上一个状态,需要写成函数的方式
修改state的唯一方式是setState()
- setState()是异步
- 函数式的setState((prevState,prevProps)=>({}),()=>{})
这个方法
setState
传入的第一个参数,可以是一个对象,也可以是一个函数
- 是一个对象,这个对象中包含需要改变的属性,它会与原有的状态进行合并
- 是一个函数,接收第一个参数是 prevState,上一个状态对象,第二个参数是 props
这个方法的第二个参数,是一个回调函数,在状态改变之后执行。
数组解构遍历
数组解构遍历要是数组的map方法,注意key的使用
import React from 'react'
const arr = [1, 2, 3]
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0,
}
}
add() {
this.setState(
(prevState, prevProps) => ({
count: prevState.count + 1,
}),
() => {
console.log(this.state.count)
}
)
}
render() {
return (
<div className="container" style={{ color: 'red', marginTop: 20 }}>
//通过map()方法遍历,因为有返回值
<ul>
{arr.length>0 && arr.map((item)=>{
<li key={item} id={item}>
{item}
</li>})
}
</ul>
</div>
)
}
}
export default App
React.createRef()创建ref对象
在React中,类似于Vue,可以通过ref
标记元素,然后通过this.refs
获取元素,只是Vue中使用的是this.$refs
获取元素
Refs 是使用 React.createRef()
创建的,并通过 ref
属性附加到 React 元素。在构造组件时,通常将 Refs 分配给实例属性,以便可以在整个组件中引用它们。
import logo from './logo.svg'
//使用React.createRef()创建ref
class App extends React.Component {
constructor(props) {
super(props)
this.imgDomRef = React.createRef()
}
render() {
return (
<div className="container" style={{ color: 'red', marginTop: 20 }}>
<img src={logo} alt="" ref={imgDomRef } />
</div>
)
}
}
export default App
使用回调函数方式
import logo from './logo.svg'
//使用回调函数创建ref
class App extends React.Component {
constructor(props) {
super(props)
this.imgDom = null
this.setImgDomRef = element=>{
this.imgDom = element
}
}
render() {
return (
<div className="container" style={{ color: 'red', marginTop: 20 }}>
<img src={logo} alt="" ref={this.setImgDomRef} />
</div>
)
}
}
export default App
父子组件通信
组件创建方式:函数式组件(只有props,展示),class类组件(state,props)
App.js
原生的js事件,注意以下this指向(箭头函数)
import React from 'react'
import Child from './Child'
class App extends React.Component {
constructor(props) {
super(props)
}
onHandleClick(val) {
console.log(val)
}
render() {
return (
<div>
//子组件使用 开头大写,否则会被视为标签。
<Child
name="kiki"
onHandleClick={(val) => this.onHandleClick(val)}
></Child>
</div>
)
}
}
export default App
Child.js
使用this.props来接收父组件传过来的属性值
import React, {Component} from 'react'
export default class Child extends Component{
constructor(props){
super(props)
}
handleClick(){
// console.log(this.props)
this.props.onHandleClick('kiki')
}
render(){
return (
<>
<h3>{this.props.name}</h3>
<button onClick={()=> this.handleClick()}>触发</button>
</>
)
}
}
生命周期
挂载
当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:
- constructor()在 React 组件挂载之前,会调用它的构造函数
- static getDerivedStateFromProps()
- render() class 组件中唯一必须实现的方法
- componentDidMount()在组件挂载后(插入 DOM 树中)立即调用
注意:
下述生命周期方法即将过时,在新代码中应该避免使用它们:
更新
当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下:
- static getDerivedStateFromProps()
- shouldComponentUpdate()性能优化点,比较父组件与子组件是否需要更新,需要返回true
- render()如果
shouldComponentUpdate()
返回 false,则不会调用render()
- getSnapshotBeforeUpdate()
- componentDidUpdate()会在更新后会被立即调用。首次渲染不会执行此方法
注意:
下述方法即将过时,在新代码中应该避免使用它们:
卸载
当组件从 DOM 中移除时会调用如下方法:
- componentWillUnmount()会在组件卸载及销毁之前直接调用
错误处理
当渲染过程,生命周期,或子组件的构造函数中抛出错误时,会调用如下方法:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class SubChild extends Component {
shouldComponentUpdate(nextProps, nextState) {
if(nextProps.count > 1000){
return false
}
return true
}
render() {
console.log('子组件渲染了')
return <div>子组件的值:{this.props.count}</div>
}
}
class NewLifeCycle extends Component {
constructor(props) {
super(props)
console.log('1.初始化组件')
this.state = {
count: props.count,
isUpdate: false,
}
}
// 此方法是静态方法,不能访问this,替代componentWillReceiveProps
static getDerivedStateFromProps(nextProps, prevState) {
console.log('2.组件接受属性和状态', nextProps, prevState)
const { isUpdate } = nextProps
if (isUpdate !== prevState.isUpdate) {
return {
count: prevState.count,
}
}
// 否则 对于state不进行任何操作
return null
}
// componentWillMount() {}
componentDidMount() {
console.log('3.组件已经挂载')
}
// componentWillReceiveProps(nextProps) {}
shouldComponentUpdate(nextProps, nextState) {
return true
}
// componentWillUpdate(nextProps, nextState) {}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('更新之前被调用', prevState)
return null
}
componentDidUpdate(prevProps, prevState) {
console.log('组件更新完成')
}
componentWillUnmount() {
// 清空定时器
console.log('组件将要卸载')
}
updateCount() {
this.setState((prevState) => {
return {
count: prevState.count + 100,
isUpdate: true
}
})
}
render() {
console.log('组件渲染')
return (
<div>
测试生命周期钩子 {this.state.count}
<button onClick={() => this.updateCount()}>更新</button>
<SubChild count={this.state.count}></SubChild>
</div>
)
}
}
NewLifeCycle.propTypes = {}
export default NewLifeCycle
运行