React是什么
如何创建react应用
npx create-react-app XXX
JSX语法
它被称为 JSX,是一个 JavaScript 的语法扩展。我们建议在 React 中配合使用 JSX,JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。JSX 可能会使人联想到模版语言,但它具有 JavaScript 的全部功能。
- 在JSX中嵌入表达式
- JSX本身也是一个表达式,所以可以把JSX当作参数传入,以及从函数中返回JSX
- JSX特定属性
// 通过引号(对于字符串)
const element = <div tabIndex="0"></div>;
// 通过大括号(对于表达式)
const element = <img src={user.avatarUrl}></img>;
元素渲染
由React DOM负责渲染我们的react元素
const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));
组件&Props
注意: 组件名称必须以大写字母开头。React 会将以小写字母开头的组件视为原生 DOM 标签。
所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。
State&生命周期
1、构造函数是唯一可以给this.state赋值的地方
class XX extends react.component {
constructor(props) {
super(props)
this.state = { msg: '直接赋值' } // 此处可以直接给state赋值
}
// Wrong 此处不能直接赋值
fn() {
this.state = { msg: '重新赋值' }
}
// Correct 此处可通过this.setState()更新state
fn() {
this.setState({ msg: '重新赋值' })
}
}
2、state的更新可能是异步的
出于性能考虑,React 可能会把多个
setState()
调用合并成一个调用。
因为this.props
和this.state
可能会异步更新,所以你不要依赖他们的值来更新下一个状态。
// Wrong 以下代码可能无法更新计数器
this.setState({
counter: this.state.counter + this.props.increment
})
/**
* Correct
* 为了解决上述问题,可以让setState()接受一个函数而不是一个对象
* 这个函数用上一个state作为第一个参数, 将此次更新被应用时的props作为第二个参数!
*/
this.setState((state, props) => {
counter: state.counter + props.increment
})
事件处理
1、事件中的this绑定
- 在构造器中绑定
// 官方推荐,不过麻烦之处在于,方法多了以后,需在构造器中逐一绑定有点麻烦
constructor(props) {
super(props)
this.fn = this.fn.bind(this) // 通过显示的绑定this
}
fn() {
console.log('this', this)
}
render (
<div onClick={this.fn}>点击看this</div>
)
- 在回调中使用箭头函数绑定
fn() {
console.log('this', this)
}
render (
<div onClick={() => this.fn()}>点击看this</div>
)
- 在回调中使用bind绑定
fn() {
console.log('this', this)
}
render (
<div onClick={this.fn.bind(this)}>点击看this</div>
)
- 使用实验性语法(不推荐,因为随时可能会变)
回调中使用
箭头函数绑定
或bind绑定
this的问题在于每次渲染组件时都会创建不同的回调函数。在大多数情况下,这没什么问题,但如果该回调函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。我们通常建议在构造器中绑定或使用 class fields 语法来避免这类性能问题。
2、事件传参
箭头函数方式,需要显示的传递事件对象e
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
bind方式,事件对象e及更多的参数将会被隐式的进行传递
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
组合和继承
React 有十分强大的组合模式。我们
推荐使用组合而非继承
来实现组件间的代码重用。
在 Facebook,我们在成百上千个组件中使用 React。我们并没有发现需要使用继承来构建组件层次的情况。
react的props.children类似于vue中的slot插槽
import React, { Fragment } from 'react'
function SplitPane(props) {
return (
<div>
<div>子组件显示内容为:</div>
{/* 父组件调用此组件时插入的内容 */}
{props.children || '无'}
</div>
)
}
function App() {
return (
<SplitPane>
<div>hello</div>
<div>world</div>
</SplitPane>
)
}
export default App
react中类似vue的具名插槽
import React, { Fragment } from 'react'
function SplitPane(props) {
const layout = {
display: 'flex',
}
const lfStyle = {
flex: 1,
backgroundColor: 'orange',
}
const rtStyle = {
flex: 1,
backgroundColor: '#383838',
}
return (
<div style={layout}>
<div className="left" style={lfStyle}>
{/* 预留的洞 */}
{props.left}
</div>
<div className="right" style={rtStyle}>
{/* 预留的洞 */}
{props.right}
</div>
</div>
)
}
function Lf(props) {
return <div>左边</div>
}
function Rt(props) {
return <div>右边</div>
}
function App() {
return <SplitPane left={<Lf />} right={<Rt />}></SplitPane>
}
export default App
<Lf /> 和 <Rt/>
之类的React元素本质上就是对象,所以可以把它们当作props,像其他数据一样传递。