React 和TypeScript 练习笔记(一)——简单交互与CP模式
本系列为Lemoncode开源项目(其中之一)练习总结,原项目共有15个练习,经我的分析,主要可归五个练习:
- 1 简单交互与CP模式
- 2 开发复合状态值的组件
- 3 表格数据与后端缓存
- 4 路由与表单验证
- 5 Context与会话状态
第一个练习由前6 个子练习组成,目的归结起来主要为了展示 最经典的React 组件模式——CP模式。
00 Boiler plate
01 Hello React
02 Properties
03 State
04 Callback
05 Refactor
06 Enable
CP模式
CP模式就是 Container-Presenter模式(容器与展示组件模式)。前端开发中最常见的任务莫过于 组件的粒度(或功能分配)的设计,就是 将一个大组件分拆为多个子组件的最佳实践。例如 “在一个VX组件 中应该将状态放在组件树的哪里最合适?”,“lifting state up” 就是社区的一种经验见解,其实本质是 Container-Presenter模式。
Container-Presenter模式 是种 父子关系的组件结构,父组件是一个容器组件,负责初始化交互状态,保持交互状态,和定义操作状态的逻辑(一般是交互事件处理,也不尽然); 子组件 是一展示型组件,负责交互输出——将交互结果(状态)渲染出来,也负责接受用户交互输入。
由于被分割了,组合它们是靠React props技术,包括data props 和 callback props。
项目功能
练习项目的交互功能 非常的简单,就是 用一个输入框接受用户的键盘输入,点击界面按键(鼠标输入)后 更新状态输出来,没有任何处理。
项目技术遗漏
本练习项目还有一些不太明显的技术要点:
第一,双向绑定和 受控组件
React 没有自动双向绑定的概念,只有受控组件,并且需要手动配置;由于功能是编辑完后点击后才渲染出来,所以 输入框的受控状态 不是渲染出来的那个状态(看源码容器组件有两个状态值),并且每编辑输入框一次,组件都重渲染;
第二,交互辅助状态
组件实现一项常见的用户友好体验的交互功能,就是在合适时候,更新按键才可用。由于逻辑较简单,此功能不需一个额外的 交互状态,它是 输入框状态的 派生状态(7第4和24行)。
交互流程,逻辑比较 复杂的时候,就会出现交互辅助状态,来提高用户交互体验。
项目结构分析
├── package.json
├── src
│ ├── app.tsx // 顶层父组件(容器组件)
│ ├── hello.tsx // 交互状态输出的子组件(展示组件)
│ ├── index.html //
│ ├── index.tsx //
│ └── nameEdit.tsx // 交互状态输入的子组件(展示组件)
├── tsconfig.json
└── webpack.config.js
项目代码简要分析
app.tsx
import * as React from "react";
import { HelloComponent } from "./hello";
import { NameEditComponent } from "./nameEdit";
export const App = () => {
const [name, setName] = React.useState("defaultUserName");
const [editingName, setEditingName] = React.useState("defaultUserName");
const loadUsername = () => { };
React.useEffect(() => { loadUsername(); }, []);
const setUsernameState = () => {
setName(editingName);
};
return (
<>
<HelloComponent userName={name} />
<NameEditComponent
editingName={editingName}
onNameUpdated={setUsernameState}
onEditingNameUpdated={setEditingName}
disabled={editingName === "" || editingName === name}
/>
</>
);
};