组件
组件的的提取
从经验来看,某些可能被复用的部分可以被提取为组件,包括业务逻辑处理以及UI表示。当然,如果一个画面相当的大,那么我们也应该给拆分分组件
- 根据设计稿设计出组件数
- 一个组件负责一个功能,尽可能不在render中使用if...else if...else
- 先出静态画面,再完成交互。交互时,仅定义必须的state,严禁乱用state
- 该数据是否是由父组件通过 props 传递而来的?如果是,那它应该不是 state。
- 该数据是否随时间的推移而保持不变?如果是,那它应该也不是 state。
- 你能否根据其他 state 或 props 计算出该数据的值?如果是,那它也不是 state。
- 确定state的位置
- 找到根据这个 state 进行渲染的所有组件。
- 找到他们的共同所有者(common owner)组件(在组件层级上高于所有需要该 state 的组件)。
- 该共同所有者组件或者比它层级更高的组件应该拥有该 state。
- 如果你找不到一个合适的位置来存放该 state,就可以直接创建一个新的组件来存放该 state,并将这一新组件置于高于共同所有者组件层级的位置。
- 反向数据流的建设
函数声明组件与类声明组件
- 函数声明
const Acomponent = (props) => {
return (
<h2>Hello</h2>
)
}
// 或
function Bcomponent(props){
return (
<h2>Hello</h2>
)
}
- 类声明
class Bcomponent extends React.Component{
constructor(props){
super(props)
}
render(){
return (
<h2>Hello</h2>
)
}
}
有状态组件与无状态组件
props
React组件必须像纯函数一样,不改变入参,也就是props不可改变。与VUE中props的不同在于,React 的 props 中始终含有属性children 与vue不同之处还在与你可以把任何东西作为props传递给子组件,vue【槽 slot】的概念在React中并不存在,都可以使用props
state
- 不可以直接修改state
- setState更新是异步的,会把多个setState合并到一起完成更新,state的再赋值是在render函数中完成。所以在开发中常见的现象是使用完setState,然后在获取state值,发现值没有改变。应该setState中挂载回调函数比如setState({}, ()=>{//get state})
- 数据是向下传递的,state的作用域是局部的,setState是浅合并
event,事件处理
在函数声明组件中
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
在类声明组件中
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 为了在回调中使用 `this`,这个绑定是必不可少的
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({ isToggleOn: !state.isToggleOn }));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
class LoggingButton extends React.Component {
// 此语法确保 `handleClick` 内的 `this` 已被绑定。 // 注意: 这是 *实验性* 语法。 handleClick = () => { console.log('this is:', this); }
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// 此语法确保 `handleClick` 内的 `this` 已被绑定。 return ( <button onClick={() => this.handleClick()}> Click me
</button>
);
}
}
// 此语法问题在于每次渲染 `LoggingButton` 时都会创建不同的回调函数。在大多数情况下,这没什么问题,但如果该回调函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。我们通常建议在构造器中绑定或使用 class fields 语法来避免这类性能问题。
表单
- textare重新封装
- select封装
均使用了value和onChange
着重说明一下受控组件与非受控组件
状态提升
将子组件的状态提升到父组件中