react.js
react.js引入后可以使用
- 创建虚拟dom
React.createElement(type,props,children)- type 虚拟dom类型,可写入'h1'等标签类型
- props 属性,当前标签可用属性接可
- children 子元素,也就是需要写入的内容
创建多个子元素,用jsx实现更好,但顶层元素只能有一个
js
React.createElement("header",{id: "title"},
React.createElement("h1", null, "hello"),
React.createElement("p", null, "nihao")
)
虚拟dom
对象类型,console.log如下

优点:按需渲染性能好
reactDom
react-dom.js引入后可以使用
- dom渲染
ReactDOM.render(element, container, callback)
element: 要渲染的内容
container: 渲染内容的容器
callback: 渲染后的回调函数,非必传
jsx
=js+xml,在js中使用xml语法
需要引入babel,引入后在script标签上用type='text/babel'指定
js
ReactDOM.render(
<header id='title' style="{{color: 'red',...}}">
<h1>...<h1>
...
</header>
)
class->className
style接收一个对象(第一个{}是插值的,第二个才是对象的)
插值表达式
注意不要加''会被识别为字符串
可以叠加js表达式(会返回一个值的,正则等),但不能用if,while,for等语句
js
let text = document.querySelector('#text')
ReactDOM.render(
<div> { text.value }</div>
)
在函数里用jsx最好在return时用()包裹一下
注释需要写在插值{/* .注释内容... */}里再注释
布尔值、空和未定义都会直接被忽略,不能输出对象(直接报错),数组可以(会用空白替换,分割)
- 列表渲染
jsx不能写循环语句,但可以把页面元素放到数组里,再让jsx渲染数组
在项目中需要给重复的元素增加key属性
react工程
createReactApp命令
npm i create-react-app
create-react-app my-app // my-app是自定义的工程文件夹名
如果报错可以尝试npx create-react-app my-app,npx 会自动查找当前依赖包中的可执行文件,如果找不到,就会去 PATH 里找。如果依然找不到,就会帮你安装。

- eject 不可逆的抛出配置
项目目录
index.js入口文件,会引入App.vue
App.vue全局根组件
大写组件小写标签
函数式组件
函数名称=组件名
函数返回值=组件渲染内容,需要返回一个reactElement
js
function App(props) {
return (<h1>HELLO</h1>)
}
第0个参数是父组件传来的props
没有string ref,this和生命周期(无状态组件),除了hooks之外所以的变量都会在更新时重新创建(无法在外部定义变量)
尽量避免子函数 每次更新会创建新函数
类式组件
必须继承自React.Component
组件必须定义render方法,写明渲染内容
js
import React from 'react'
class App extends React.Component { // 继承自React的组件类
render() {
return <h1>HELLO</h1>
},
constructor(props) {
super(props) //继承父组件
}
}
- this里有:
props:父组件传来的数据- state: 用于定义和保存数据变量
可以直接定义,变成类的一个属性
- state: 用于定义和保存数据变量
js
import React from "react";
// import {Component} from "react"也可以extends Component
class App extends React.Component {
state = {
name: 'ssss',
num: 1
}
render() {
return <button onClick={}>HELLO</button>
}
}
修改state:
js
setState(
{
// 要修改的state部分
},
() => {
// 状态更新完之后需要执行的回调函数,非必填
}
}
修改state并会重新渲染组件,直接修改this.state 组件不会重新渲染
react会对多次修改合并,只render一次
js
setNum= () => { // 事件名称需要驼峰
let {name,num} = this.state
this.setState({num: ++num})
}
- constructor构造函数
需要super继承父级
要定义变量只能在constructor或原型上
-事件
没有this,需要用箭头函数
路由和store的包裹关系
index.js
js
import store from './redux/index'
import {Provider} from 'react-redux'
import { BrowserRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter><App /></BrowserRouter>
</Provider>
</React.StrictMode>
);
store包裹router
react API
组件间通信
- 子组件-父组件
把数据和数据更新的回调方法放在props里
js
// 父组件
state = {
openChlid: '1'
}
setOpen=(chlidName) => {
// 需要绑定this,所以要用箭头函数定义成属性
this.setSate({
openChild: chlidName
})
}
render() {
return(<List isOpen={openChild === item.name} date={datas[item]} />)
}
// 子组件
render() {
let {setOpen} = this.props
setOpen('1')
}
跨组件
context 不推荐直接在项目中使用
js
// --------父组件
import {createContext} from "react";
let {Provider,Consumer} = createContext(defaultVaule) // 可以传默认值
return (<Provider vaule={{data}}>
<div><List Consumer={Consumer}/></div>
</Provider>)
// ---------子组件
let {Provider,Consumer} = this.props
return(<Consumer>
{ (props) => {return (<Son {...props} />)} }
</Consumer>)
createContext提供两个组件Provider和Consumer,提供参数的组件用Provider包裹要用到数据的子组件,用vaule属性传参
不结合第三方插件的话,Consumer需要自己做Props传下去
需要使用数据的组件要用Consumer标签包裹,并在箭头函数里返回,回调函数里会有props参数,就是传递的数据
生命周期
react16.3之前
- 挂载
constructor() → componentWillMount() → render() → componentDidMount()- - 更新阶段:组件因props或state变化而重新渲染
componentWillReceiveProps(nextProps) (且只有父组件更新引起组件更新会触发)→ shouldComponentUpdate(nextProps, nextState) → componentWillUpdate(nextProps, nextState) → render() → getSnapshotBeforeUpdate() *(16.3之前没有)*→ componentDidUpdate(prepProps, prevState, prevHtml)
shouldComponentUpdate() { 需要return一个boolean值表示是否更新,return false打断不更新视图}
16.3之后提供静态方法替代componentWillReceiveProps,但不建议使用,但可以用于state和prop中的数值绑定
js
static getDerivedStateFromProps(props,state) {
console.log('父组件引起当前组件更新的参数',props, state)
state.val = props.data.val // 可以用于state和prop中的数值绑定
return true; // 返回false也没用
}
- 卸载阶段:组件从DOM中移除
componentWillUnmount() - 错误处理 16.3之后才有
在父组件中写,捕获子组件生命周期的错误,不捕获事件中的错误
static getDerivedStateFromError(error): 静态方法,error是true,方法里返回一个对象可以直接更新组件的state
componentDidCatch(err, info):API,能拿到this, info能拿到具体的出错信息
受控组件
非受控组件:不需要同步value值的表单控件 用defaultVaule或defaultCheck属性
受控组件:通过onChange事件更新state里的数据的表单控件
PureComponent
和Component比在加载性能上更好,setState提供的是浅比较的shouldComponentUpdate,浅比较相同的不会触发render
state中的引用对象修改记得引用新地址,即使用新对象
children
js
// 父组件
render() {
return(
<Alert>
<p>children1</p>
<p>children2</p>
</Alert>
)
}
// Alert子组件
render() {
let {children} = this.props
return(
<div>
<p>...</p>
{children}
</div>
)
}
需要自定义传参的用prop传组件或返回组件的回调函数
js
// 父组件
class Btn extends PureComponent {
render() {
return(<button onClick={() => {this.props.hide();}}>CLOSE</button>)
}
}
render() {
return(
<Child Child={Btn}}></Child>
// 或
<Child renderCb={() => {return <Btn {...this.props}/>}}></Child>
)
}
// Alert子组件
hide=() => {
...
}
render() {
let {Child} = this.props
return(
<div>
<p>...</p>
<Child hide={() => {this.hide}}></Child>
// 或
{ renderCb({hide: this.hide}) }
</div>
)
}
dangerouslySetInnerHTML
转字符串到html
js
import { PureComponent } from "react";
const innerHtmlStr = `<section><h1>11111</h1><section/>`
export default class danger extends PureComponent {
render() {
return(<div
dangerouslySetInnerHTML={{
__html: innerHtmlStr
}}
>
</div>)
}
}
refs
在组件挂载、更新完成之后使用
String ref:老版本,不向下兼容
js
import { PureComponent } from "react";
export default class danger extends PureComponent {
render() {
return(<div>
<input
ref="txt"
/>
</div>)
}
componentDidUpdate() {
this.refs.txt // 对应的dom元素
}
}
方二 createRef
js
import { PureComponent, createRef } from "react";
export default class danger extends PureComponent {
state = {
txtRef:createRef()
}
render() {
return(<div>
<input
ref={this.state.txtRef}
/>
</div>)
}
componentDidUpdate() {
this.state.txtRef.current // 对应的dom元素
}
}
hooks
只能在函数式组件或其他hook里用
只能在顶层使用=不能在if或for里用
use开头的都是钩子函数
react提供的:
useState
sate, setState\] = useState(initSate) useState返回的是一个数组,sate当前对应的状态,setState修改对应state的方法 返回的setState也是浅对比 对一个对象useState之后返回的setState是直接替换,而不是合并赋值 ```js // -------子组件 function Child(props) { // const {name, setName} = props; const {state, setState} = props; let {name, count} = state return(
name: {name}
{ // setName(e.target.value) setState({ ...state, // 对对象使用时是直接替换,需要把原有的加进来 name: e.target.value }) }} >count: {count}
{ // setName(e.target.value) setState({ ...state, count: e.target.value }) }} >