React 应用程序是由组件组成的。
-
react 程序是用的jsx语法,使用这种语法的代码需要由babel进行解析,解析成js代码。
jsx语法:
-
只能返回一个根元素
-
所有的标签都必须闭合(自闭和或使用一对标签的方式闭合)
-
使用驼峰式命名法给大部分属性命名如:className
-
大写字母开头的标签一般都是组件
-
jsx标签的属性,使用引号传递字符串,使用一组
{
和}
传递js变量,且大括号中可以写js的表达式
,也可以传递使用个另外一对额外的大括号包裹对象。 -
标签中可以使用三目运算符
在 JSX 中,
{cond ? <A /> : <B />}
表示 "当cond
为真值时, 渲染<A />
,否则<B />
"在 JSX 中,
{cond && <A />}
表示 "当cond
为真值时, 渲染<A />
,否则不进行渲染"。jsreturn ( <li className="item"> {isPacked ? name + ' ✔' : name} </li> );
-
渲染列表:使用map()方法生成一组相似组件,使用filter()方法来筛选数组
jsconst listItems = chemists.map(person => <li>...</li> // 隐式地返回! ); const listItems = chemists.map(person => { // 花括号 return <li>...</li>; });
-
-
组件引入语法用到了ES6的模块化编程语法
-
解构赋值语法:可以将数组中的值或对象的属性取出,赋值给其他变量。
-
展开运算符:
jsfunction Profile({ person, size, isSepia, thickBorder }) { return ( <div className="card"> <Avatar person={person} size={size} isSepia={isSepia} thickBorder={thickBorder} /> </div> ); } {/* 关于Avatar那一部分可以写成 */} <Avatar {...props} />
-
-
React 三大元素:
-
State对象(要将state视为只读的)
在数据发生改变之后页面上的内容才会重新渲染、
- 设置 state 不会更改现有渲染中的变量,会请求一次新的渲染。
- React 将 state 存储在组件之外,就像在架子上一样。
- 当你调用
useState
时,React 会为你提供该次渲染 的一张 state 快照。
更新state对象时要传递一个新的值,即使时一个json对象。
- 你可以使用这样的
{...obj, something: 'newValue'}
对象展开语法来创建对象的拷贝。
更新state中的数组:
推荐使用(会返回一个新数组) 添加元素 concat,[...arr] 删除元素 filter,slice 替换元素 map 排序 先将数组复制一份儿 可以使用 Immer 来保持代码简洁。
相同UI树上的元素的State将会被保留,位置不同的组件会使state重置
- 你可以通过为一个子树指定一个不同的 key 来重置它的 state。
-
props对象
在标签上添加属性,即可给组件添加prop属性。在子组件中可以通过props读取到对应的属性,解构赋值时可以给一个默认值
javascriptfunction Avatar({ person, size = 100 }) { // ... }
组件间共享状态:可以通过状态提升的方式,让后再通过props传递给子组件。
通过context上下文传递参数
-
创建context
jsimport { createContext } from 'react'; export const LevelContext = createContext(1);
-
使用context
js{/* 组件会使用 UI 树中在它上层最近的那个 <LevelContext.Provider> 传递过来的值。 */} import { LevelContext } from './LevelContext.js'; const level = useContext(LevelContext);
-
提供context
js{/* 在父组件中设定对应的值 */} <section className="section"> <LevelContext.Provider value={level}> {children} </LevelContext.Provider> </section>
-
-
ref对象
-
-
React的交互:
-
给元素的事件传递一个函数,而调用一个函数。
js<button onClick={handleClick}> {/* 正确 */} <button onClick={handleClick()}>{/* 错误 */}
-
-
在 React 中,
useState
以及任何其他以"use
"开头的函数都被称为 Hook。-
使用
useImmerReducer
可以将通知同一个state的方法,组织到一起。提高代码的可读性。- 把
useState
转化为useReducer
:- 通过事件处理函数 dispatch actions;
- 编写一个 reducer 函数,它接受传入的 state 和一个 action,并返回一个新的 state;
- 使用
useReducer
替换useState
;
jsimport { useImmerReducer } from 'use-immer'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; function tasksReducer(draft, action) { switch (action.type) { case 'changed': { const index = draft.findIndex((t) => t.id === action.task.id); draft[index] = action.task; break; } case 'deleted': { return draft.filter((t) => t.id !== action.id); } default: { throw Error('未知 action:' + action.type); } } } export default function TaskApp() { const [tasks, dispatch] = useImmerReducer(tasksReducer, initialTasks); function handleChangeTask(task) { dispatch({ type: 'changed', task: task, }); } function handleDeleteTask(taskId) { dispatch({ type: 'deleted', id: taskId, }); } return ( <> <h1>布拉格的行程安排</h1> <AddTask onAddTask={handleAddTask} /> <TaskList tasks={tasks} onChangeTask={handleChangeTask} onDeleteTask={handleDeleteTask} /> </> ); } let nextId = 3; const initialTasks = [ {id: 0, text: '参观卡夫卡博物馆', done: true}, {id: 1, text: '看木偶戏', done: false}, {id: 2, text: '打卡列侬墙', done: false}, ];
- 把
-