React 和TypeScript 练习笔记(二)—— 开发复合状态值的组件
本系列为Lemoncode开源项目(其中之一)练习总结,原项目共有15个练习,经分析,主要可归结为五个练习:
- 1 简单交互与CP模式
- 2 开发复合状态值的组件
- 3 表格数据与后端缓存
- 4 路由与表单验证
- 5 Context与会话状态
第二组练习由7、8、9 三个子练习组成,目的归结起来主要为了展示
- 开发复合交互状态值 (object)组件,和CP组件模式
- 以及 children props 组件 API 的使用
07 ColorPicker
Simple color picker demo (show how properties work).
08 ColorPicker Refactor
09 Sidebar
Implementation of a single sidebar.
复合状态值 的交互处理
本练习的重点,是复合交互状态(color{blue,red,green})的处理,复合值 在组件间传递会增加出错的概率,为了保证这种 处理 的低bug率,TypeScript 派上用场。用上TS保证安全,代码变得“繁盛”起来,学习和适用需要点时间。
组件功能
先从 了解 组件功能
1 调色组件功能
界面上有一色块组件(colorBrowser) ,它的值是复合的 由 color 状态保存,并有三个类似的调色控件(colorPicker) 调整 三原色的值(blue,red,green)。
这个功能 还是典型 CP模式实现,只是容器保存是 复合值color{blue,red,green},通过prop传递 和setState都要保证类型正确;另外,三个调色控件功能是相似,可以进一步抽象成通用组件复用,此为 professional 组件模式。
├── package.json
├── src
│ ├── app.tsx // color 状态容器
│ ├── components //
│ │ ├── colorBrowser.tsx // color 状态展示组件(输出)
│ │ ├── colorPicker.tsx // color 状态展示组件(输入)
│ │ ├── index.tsx
│ │ ├── sidebar.css
│ │ └── sidebar.tsx //
│ ├── index.html
│ ├── index.tsx
│ └── model // 前端 交互状态的数据模型
│ └── color.ts // 复杂交互状态的类型定义
│── tsconfig.json
└── webpack.config.js
2 弹出菜单的功能
此功能与前一个功能是不相关的,只是都使用了CSS。此功能主要为展示 children props组件 API,和CSS的使用。
功能非常简单,顶层容器组件有一个sidebar,开合由一个isVisible状态控制(由顶层组件 把持),isVisible有一个 Toggle 按键控制。
项目技术分析
第一,TypeScript 和Color 类型的使用
TypeScript 或强类型编程的意义可概括这样的一句话:大程序是被分割成模块的,模块之间存调用关系(进行分拆后的合并),当我们制作一通用模块(被调用模块)时要注意接口的类型,同样当我们调用(使用)这些模块功能 也要关心使用适当的类型。
有过C和JAVA背景的人会认为,所有符号都要声明类型,但TS只是JS的超集,没有声明的符号变量依然是合法TS代码,所以像一些类型很明显的地方可忽略类型声明,例如本地变量。
前端开发的 组件模块拆分 是常见,主要有专业分拆(例如CP模式组件),和复用拆分(例如 自定义HOOK)。例如如下 调色组件的 两个展示组件(ColorBrowser ColorPicker)的类型定义:
interface Color { red: number; green: number; blue: number;}
interface Props { color: Color;}
const ColorBrowser: React.FC<Props> = (props) => {}
interface Props { color: Color; onColorUpdated: (color: Color) => void;}
const ColorPicker: React.FC<Props> = (props) => ()
调用时需要使用适当的类型( 这里的color setColor 是 React.useState声明的)
<ColorBrowser color={color} />
<ColorPicker color={color} onColorUpdated={setColor} />
const [color, setColor] = React.useState<Color>({ red: 20, green: 40, blue: 180 });
第二,CSS的使用
界面CSS渲染,本练习只使用最简单的CSS技术
第三,components目录
为了整理 分拆的 组件,独立出一个components目录,index集中导出
项目代码简要分析
import { ColorBrowser, ColorPicker, SidebarComponent} from "./components";
import { Color } from "./model/color";
export const App = () => {
const [color, setColor] = React.useState<Color>({
red: 20,
green: 40,
blue: 180
});
const [isVisible, setVisible] = React.useState(false);
return (
<>
<SidebarComponent isVisible={isVisible}>
<h1>Cool Scfi movies</h1>
<ul>
<li>
<a href="https://www.imdb.com/title/tt0816692/">Interstellar</a>
</li>
<li>
<a href="https://www.imdb.com/title/tt0083658/">Blade Runner</a>
</li>
<li>
<a href="https://www.imdb.com/title/tt0062622/">
2001: a space odyssey
</a>
</li>
</ul>
</SidebarComponent>
<ColorBrowser color={color} />
<ColorPicker color={color} onColorUpdated={setColor} />
<div style={{ float: "right" }}>
<button onClick={() => setVisible(!isVisible)}>Toggle Sidebar</button>
</div>
</>
);
};