react是三大前端主流框架之一。它有着庞大多生态体系,几乎所有开发需求都有成熟的解决方案;它上手简单,可在几小时内上手React技术,但知识很广,需要更多时间才能完全驾驭;它社区强大,使用人群多,可以很容易的找到志同道合的人一起学习
开发环境
本文使用的react版本:v16.8.6
需要确保电脑上的环境:Node >= 6
and npm >= 5.2
创建项目
npx create-react-app my-app
cd my-app
npm start
配置
// 根目录下新建 config-overrides.js
const { override, fixBabelImports, addLessLoader, addWebpackAlias, useEslintRc } = require('customize-cra')
const path = require('path')
module.exports = override(
// 配置antd按需引入
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true
}),
// 配置less
addLessLoader({
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1890ff' }
}),
// 配置别名
addWebpackAlias({
['@']: path.resolve(__dirname, 'src')
}),
// 使用eslint
useEslintRc()
)
JSX
JSX就是JS和XML结合的一种格式。React发明了JSX,可以方便的利用HTML语法来创建虚拟DOM,当遇到<,JSX就当作HTML解析,遇到{就当JavaScript解析.
// 最基本的jsx
const element = <h1>Hello, world!</h1>
// 复杂的jsx
<ul className="list">
<li>{message}</li>
<li>{right ? 'right' : 'left'}</li>
</ul>
// React渲染到页面
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
)
组件
React要求必须在一个组件的最外层进行包裹,如果代码中不需要多余的标签,可用React.Fragment
包裹,此时打包后不会产生新标签
- class组件
// App.js
import React, {Component} from 'react'
class App extends Component{
render(){
return (
<div>
Hello World
</div>
)
}
}
export default App
- 函数组件
const App = props => (
<div>{props.message}</div>
)
- 组合组件
function Welcome(props) {
return <h1>Hello, {props.name}</h1>
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
)
}
Props和State
Props
下列函数不会尝试更改入参,且多次调用下相同的入参始终返回相同的结果,这就是纯函数
function sum (a, b) {
return a + b;
}
- 组件无论是使用函数声明还是通过
class
声明,都决不能修改自身的 props - 所有 React 组件都必须像纯函数一样保护它们的 props 不被更改
State
- 不要直接修改 State,应该使用
setState()
- State 的更新可能是异步的
this.setState((state, props) => ({
counter: state.counter + props.increment
}), () => console.log('本次更新完成'))
- State 的更新会被合并,互不影响
事件处理
- React 事件的命名采用小驼峰式(camelCase),而不是纯小写
- 使用
JSX
时需要传入一个函数作为事件处理函数,而不是一个字符串 - 不能通过返回
false
的阻止默认行为,必须显式的使用preventDefault
解决this指向问题
构造函数中bind
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
}
handleClick() {}
...
<button onClick={this.handleClick}>Hello</button>
HTML节点
handleClick() {}
<button onClick={this.handleClick.bind(this)}>Hello</button>
ES6 箭头函数
// 注意: 这是 *实验性* 语法。
handleClick = event => {
event.preventDefault()
// handle
}
...
<button onClick={this.handleClick}>Hello</button>
<button onClick={event => this.handleClick(event)}>Hello</button>
条件渲染和列表渲染
条件渲染
- 通过
if
判断,返回不同的JSX - 与运算符 &&
- 三目运算符
- 阻止组件渲染
return null
列表渲染->通过map
函数遍历数组
[1, 2].map(num => <li key={num}>{num}</li>)
在jsx中嵌入map
function NumberList(props) {
const numbers = props.numbers
return (
<ul>
{numbers.map((number) =>
<ListItem key={number.toString() value={number} />
)}
</ul>
)
}
受控组件和非受控组件
受控组件: 组件绑定value,监听变化,手动更新state
handleChange = event => {
this.setState({value: event.target.value})
}
...
<input value={this.state.value} onChange={this.handleChange} />
当需要处理多个 input 元素时,可以给每个元素添加 name 属性,并让处理函数根据 event.target.name 的值选择要执行的操作
非受控组件: react自己内部进行了处理
constructor(props) {
super(props)
this.handleSubmit = this.handleSubmit.bind(this)
this.input = React.createRef()
}
handleSubmit(event) {
console.log(this.input.current.value)
event.preventDefault()
}
...
<input ref={this.input} />
指定默认值
<input type="checkbox"/>
和 <input type="radio"/>
支持 defaultChecked
<select/>
和 <textarea/>
和<input/>
支持 defaultValue
react组件与html不同的几个点:
textarea
在html中通过子元素定义文本,react则使用value
属性代替select
默认选中,在html中需要在options
标签使用selected
,而在react中在select
标签上使用value
属性<input type="file" />
始终是一个非受控组件,因为它的值只能由用户设置,而不能通过代码控制
注意事项
- 使用map循环时需要设置一个唯一的
key
,否则会报错 - 删除列表的某一项
let list = this.state.list list.splice(index, 1) this.setState({ list })
- jsx中注释
{/* 注释 */}
或{ // 注释 }
- jsx中类名要使用
className
而不是class
- jsx中要标签插入html要用
dangerouslySetInnerHTML
属性 - jsx中
label
标签要使用htmlfor
而不是for
生命周期
初始化默认的属性对象
static defaultProps = {
name:'计数器'
}
初始化默认的状态对象
constructor(props) {
super(props);
this.state = {
number: 0
}
}
componentWillMount()
废弃
componentDidMount
componentWillReceiveProps()
废弃
getDerivedStateFromProps()
新增
shouldComponentUpdate()
componentWillUpdate()
废弃
getSnapshotbeforeUpdate()
新增
componentDidUpdate()
componentWillUnmount