React出现的历史
- 传统
DOM API
关注太多的细节 - 优点:
React
始终刷新整体页面
React
- 一个新概念:
组件
- 4个必须api
- 单向数据流
- 完善的错误提示
Flux 架构: 单向数据流
衍生产品: Redux Mobx
以组件方式考虑 UI构建
class CommentBox extends Component {
render () {
return (
<div>
<CommentList />
<CommentFrom />
</div>
)
}
}
- 理解 React 组件
-
props + state = View
- React 组件一般不提供方法, 而是某种状态机
- React组件可以理解为一个纯函数
- 单项数据绑定
-
创建一个简单的组件
- 创建静态
UI
- 考虑组件的状态组成
- 考虑组件的交互方式
受控组件 vs 非受控组件
- 受控: 表单元素状态由使用者维护
- 非受控: 表单元素状态
DOM
自身维护
何时创建组件: 单一职责原则
- 每个组件只做一件事
- 如果组件变得复杂, 那么应该拆分小组件
数据状态管理: DRY
原则
- 能计算得到的状态就不要单独存储
- 组件尽量无状态, 所需数据通过
props
获取
JSX: 一种语法糖
- 在
JS
代码中直接写HTML
标记
const name = 'yym'
const element = <h1>Hello, {name}</h1>
-
JSX
本质: 动态创建组件的语法糖 - 在
JSX
中使用表达式-
jsx
本身也是表达式
const element = <h1>Hello, world</h1>
- 在属性中使用表达式
<MyComponent foo={1 + 2 + 3} />
- 延展属性
const props = {firstNmae: 'yym', lastName: 'bruce'} const greeting = <Greeting {...props} />
- 表达式作为子元素
const ele = <li>{ props.name }</li>
-
-
JSX
约定: 自定义组件以大写字母开头-
React
认为小写的tag
是原生DOM
节点, 如div
- 大写字母开头为自定义组件
-
JSX
标记可以直接使用属性语法, 如<menu.Item />
-
React组件的生命周期
-
Render
阶段- 纯净且没有副作用.可能会被React暂停, 中止或重新启动
-
Pre-commit阶段
- 可以读取DOM
-
Commit
阶段- 可以使用DOM, 运行副作用, 安排更新
constructor 构造函数
- 用于初始化内部状态, 很少使用
- 唯一可以直接修改 state 的地方
getDerivedStateFromProps
- 当 state 需要从 props 初始化时使用
- 尽量不要使用: 维护两者状态一致性会增加复杂度
- 每次 render 都会调用
- 典型场景: 表单控件获取默认值
componentDidMount
- UI 渲染完成后调用
- 只执行一次
- 典型场景: 获取外部资源
componentWillUnmount
- 组件移除时被调用
- 典型场景: 资源释放
getSnapshotBeforeUpdate
- 在页面 render 之前调用,
state
已更新 - 典型场景: 获取
render
之前的 DOM 状态
componentDidUpdate
- 每次 UI 更新时被调用
- 典型场景: 页面需要根据
props
变化重新获取数据
shouldComponentUpdate
- 决定
Virtual DOM
是否要重绘 - 一般可以由
PureComponent
自动实现 - 典型场景: 性能优化
理解 Virtual DOM 和 key 属性的作用
JSX运行基础: Virtual DOM
- 虚拟DOM的两个假设
- 组件的
DOM
结构相对稳定 - 类型相同的兄弟节点可以被唯一标识:
key
- 组件的
组件设计模式: 高阶组件和函数作为子组件
高阶组件和函数子组件都是设计模式
可以实现更多场景的组件复用
-
高阶组件(HOC)
-
高阶组件接受组件作为参数, 返回新的组件
-
-
函数作为子组件
]
理解 Context API使用场景
- 根节点称为
provide
- 使用
context
称为consume
const ThemeContext = React.createContext('light')
class App extends React.Component {
render () {
return (
<ThemeContext.Provide value="dark">
<ThemeButton />
</ThemeContext.Provide>
)
}
}
function ThemeButton(props) {
return (
<ThemeContext.Consume>
{ theme => <Button {...props} themen={ theme } />}
</ThemeContext.Consume>
)
}
使用脚手架创建React应用
Create React App
Codesandbox
Rekit
为什么需要脚手架
一个项目需要的应用挺多: React
Redux
React/Router
BABEL
Webpack
ESlint
...
$ create-react-app
打包和部署
为什么需要打包? 使用
webpack
打包
- 编译
ES6
语法特性, 编译JSX
- 整合资源, 例如图片,
Less/Sass
- 优化代码体积
打包注意事项
- 设置
nodejs
环境为production
- 禁用开发时专用代码, 比如
logger
- 设置应用根路径
$ npm run build