1、安装
npm init -y // 初始化npm管理工具->生成package.json文件
npm i react react-dom //安装react
//npx是npm内置的一个命令,脚手架创建项目
npx create-react-app my-app
2、简单实用:
const title = React.createElement('h1', null, 'Hello React')
ReactDOM.render(title,document.getElementById('root'))
//jsx
const jsx = (<div className="app"><h1>Hello React! 动态变化数据:{count}</h1> </div>)
//JSX是React.createElement方法的语法糖**
//React元素的有些属性名使用小驼峰命名法
- 如果要渲染一组数据,应该使用数组的 map() 方法
- 注意:渲染列表时应该添加 key 属性,key 属性的值要保证唯一
- 原则:map() 遍历谁,就给谁添加 key 属性
- 注意:尽量避免使用索引号作为 key !
style属性{{属性:值}}
<h1 style={{ color: 'red', backgroundColor: '#eee' }}>
JSX的样式处理
</h1>
属性名小驼峰命名
<h1 className="title">
JSX的样式处理
</h1>
3、 创建组件
//函数创建组件
import React from 'react';
function Hello() {
return (
<div>这是我的第一个函数组件!</div>
)
}
ReactDOM.render(<Hello />, root)
// 类组件
import React from 'react';
class Hello extends React.Component {
render() {
return <div>Hello Class Component!</div>
}
}
ReactDOM.render(<Hello />, root)
4、 事件绑定 this问题,e
- 语法:on+事件名称={事件处理程序fn},比如:onClick={() => {}}
function handleClick(e) {
e.preventDefault()
console.log('事件对象', e)
}
<a href="http://www.baidu.com" onClick={handleClick}>点我,不会跳转页面</a>
//this 指向
//利用bind修改this指向组件实例
//利用箭头函数(推荐)
5、有状态组件和无状态组件的区别
- 函数组件又叫做无状态组件,类组件又叫做有状态组件
- 状态(state)即数据,某个时刻的值
- 类组件有自己的状态,负责更新 UI,让页面“动” 起来 (响应式)
- 函数组件没有自己的状态,只负责数据展示(静)
// 类组件中的state 和 setState
- 状态(state)即数据,是组件内部的私有数据,只能在组件内部使用
- state 的值是**对象**,表示一个组件中可以有多个数据 相当于vue的data
- 状态是可变的 this.setState({ key:val, key2:val2 })
- 注意:不要直接修改 state 中的值,这是错误的!!! ->this.state.num=2这样写不可以!
- setState() 作用:
- 修改 state
- 更新UI
- 思想:数据驱动视图
6、 表单
// 受控组件 相当于vue 中的v-model
<input type="text" value={this.state.name} onChange={changeVale}>
changeVale =(e) =>{
this.setState({
name: e.target.value;
})
}
// 非受控组件
- 说明:借助于 ref,使用原生 DOM 方式来获取表单元素值
- ref 的作用:获取 DOM 或组件实例
1. 调用 React.createRef() 方法创建一个 ref 对象
```
constructor() {
super()
this.txtRef = React.createRef()
}
```
2. 将创建好的 ref 对象添加到文本框中
<input type="text" ref={this.txtRef} />
3. 通过 ref 对象获取到文本框的值
console.log(this.txtRef.current.value)
适用场景:
- 操作DOM元素和类组件
- 控制元素样式或媒体播放等
注意
- 不能在函数**组件上**使用ref,因为它没有实例。
- 不要过度使用Refs。
7、 组件通讯
- 组件是封闭的,要接收外部数据应该通过 props 来接收
- props的作用:接收传递给组件的数据
- 传递数据:给组件标签添加属性
- 接收数据:函数组件通过参数props接收数据,类组件通过 this.props 接收数据
注意:使用类组件时,如果写了构造函数,应该将 props 传递给 super(),否则,无法在构造函数中获取到 props!
function Hello(props){
console.log(props.name);
}
<Hello name="java" />
class Hello extends React.Component{
render(){
console.log(this.props.age);
}
}
<Hello age={19} />
父传子,子组件通过props里接收父组件传值
<child name={this.state.name} />
子传父, 子组件调用通过父组件传递过来的方法,改变父组件中的值
子组件:this.props.getMsg("msg");
父组件:<Child getMsg={this.getChildMsg} />
getChildMsg(msg) =>{ console.log(msg)}
兄弟组件
- 将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态
- 思想:**状态提升** : 父->子A和子B-> 把A和B共同的state放到父组件中维护
- 公共父组件职责:1. 提供共享状态 2. 提供操作共享状态的方法
- 要通讯的子组件只需通过 props 接收状态或操作状态的方法
亲戚组件:context
作用:Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。
1. 调用 React. createContext() 创建 Provider(提供数据) 和 Consumer(消费数据) 两个组件。
const { Provider, Consumer } = React.createContext()
<Provider value="pink">
<div className="App">
<Child1 />
</div>
</Provider>
2. 使用 Provider 组件作为父节点。设置 value 属性,表示要传递的数据。
3. 调用 Consumer 组件接收数据
<Consumer>{data => <span>data参数表示接收到的数据:{data}</span>}</Consumer>
8、props深入
1、children属性
children 属性:表示组件标签的子节点。当组件标签有子节点时,props 就会有该属性,
children 属性与普通的props一样,值可以是任意值(文本、React元素、组件,甚至是函数
<Child>大哭大哭大哭</Child>
console.log(this.props.children); // 大哭大哭大哭
2、props校验
1)安装包 prop-types (npm i prop-types)
2)import PropTypes from 'prop-types';
3)function App(props) {
return (<h1>Hi, {props.colors}</h1>)
}
// 类型定义
App.propTypes = {
// 约定colors属性为array类型
// 如果类型不对,则报出明确错误,便于分析错误原因
colors: PropTypes.array
}
注意:
1. 常见类型:array、bool、func、number、object、string
2. React元素类型:element
3. 必填项:isRequired
4. 特定结构的对象:shape({ })
// 常见类型
optionalFunc: PropTypes.func,
// 必选
requiredFunc: PropTypes.func.isRequired,
// 特定结构的对象
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
})
3、props默认值
// 设置默认值
App.defaultProps = {
pageSize: 10
}
9、react生命周期

更新时(更新阶段):执行时机:1. setState() 2. forceUpdate() 3. 组件接收到新的props/作为子组件
10、组件复用
1、render props模式 2. 高阶组件(HOC)
1、
class Aa extends React.Component{
state={ name: 'aa', age: 18}
render(){
this.props.render(this.state);
}
}
<Aa render=((state)=>{console.log(state.name)}) />
2、高阶组件
const withHoc = (WrappedComponent) =>{
return class extends React.Component{
state = {
a:0
}
add=()=> {
this.setState({
a: ++this.state.a
})
}
render(){
return (
<div>
// 参数是组件
<WrappedComponent a={this.state.a} fn={this.add} />
</div>
)
}
}
}
const eComponet = withHOC(WrappedComponent);
11、路由
1、安装$ npm i react-router-dom
2、使用
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
// 路由配置和导航
<Router>
<nav className="menu">
<Link to="/home">home</Link>
</nav>
<div className="app">
<Route path="/home" component={Home} />
</div>
</Router>
**注意**:
- Router 组件:包裹整个应用,一个 React 应用只需要使用一次
- Route、Link组件:必须在Router 组件内部
动态路由
<Route path="/about/:id" component={About} />
动态路由的参数获取:this.props.match.params
编程式导航。。。
class Login extends Component {
handleLogin = () => {
this.props.history.push('/home')
}
render() {...省略其他代码}
}
12、高级
1、setState(stateChange[, callback])
第二个参数可以获取stateChange后的值
多次调用 setState() ,但是react会做批处理和覆盖,且只会触发一次重新渲染
2、setState((state, props)=>{}[, callback])
这种多次调用setState,不会覆盖,会触发多次
3、组件更新机制
setState() 的两个作用: 1. 修改 state 2. 更新组件(UI)
过程:父组件重新渲染时,也会重新渲染子组件。但只会渲染当前组件子树(当前组件及其所有子组件)
4、只渲染根组件有关的数据轻量 state:**只存储跟组件渲染相关的数据**
5、使用钩子函数 **shouldComponentUpdate(nextProps, nextState)**减少不必要的重新渲染
6、纯组件 PureComponent: 纯组件内部通过分别 对比 前后两次 props 和 state 的值,来决定是否重新渲染组件
7、虚拟 DOM:本质上就是一个 **JS 对象**,用来描述你希望在屏幕上看到的内容
- 初次渲染时,React 会根据初始state(Model)结合jsx元素结构,创建一个虚拟 DOM 对象(树)。
- 根据虚拟 DOM 生成真正的 DOM,渲染到页面中。
- 当数据**变化后**(setState()),重新根据新的数据,**创建新的虚拟DOM对象**(树)。
- 与上一次得到的虚拟 DOM 对象,使用 **Diff 算法** 对比(找不同),得到需要更新的内容。
- 最终,React 只将变化的内容更新(**patch**)到 DOM 中,重新渲染到页面。
8、diff
1、元素类型:如果两棵树的根元素类型不同,React 会销毁旧树,创建新树
2、元素属性:React 会对比两者的属性是否相同,只更新不同的属性
3、当处理完这个 DOM 节点,React 就会递归处理子节点。
4、key:
说明:key 属性在 React 内部使用,但不会传递给你的组件
推荐:在遍历数据时,推荐在组件中使用 key 属性:`<li key={item.id}>{item.name}</li>`
注意:**key 只需要保持与他的兄弟节点唯一即可,不需要全局唯一**
注意:**尽可能的减少数组 index 作为 key,数组中插入元素的等操作时,会使得效率低下**
生命周期: