深入源码分析的好处
- 自我成长需要,提升编码能力和技术深度
- 学习借鉴,应用到实际项目开发,提高开发效率
- 各种操作算法和最佳实践,提升编程功底
源码分析的准备
- 下载源码
- 安装依赖
- IDE打开,例如 webstorm,Vscode
- 找到入口文件,一般都是 index.js
- 本地调试
- 在内存中创建虚拟的DOM元素。来减少对真水DOM的操作从而提升性能
- JSX 即Javascript XML,它是对JavaScript 语法扩展。React 使用 JSX 来替代常规的 JavaScript
- DOM类型的标签,标签的首字母小写
- React组件类型的标签需要首字母大写。React也是通过首字母的大小写来判断渲染的是哪种类型的标签
- JSX表达式的,将表达式写到
{}
内即可 - JSX当中,是不能使用if else 的,不过可以使用三元运算表达式
- JSX表达式的,将表达式写到
react源码分析资料 https://react.jokcy.me/
手写 react hooks https://www.yuque.com/lijiangpeng/fiurgq
hooks源码分析 https://www.yuque.com/qqhh/react/sgorvu
https://github.com/KieSun/awesome-frontend-source-interpretation
https://react.jokcy.me/
react核心
- 单向数据流
- 数据与界面绑定
- 单向渲染,数据改变就重新渲染
- 就好像一个函数,同样的输入,同样的输出
- 组件化
- 独立,完整,自由组合
- 让组件独立出来,具备完成的独立功能,可插拔
- 保持组件的一致性,UI的一致性
- 虚拟DOM
jsx语法
- JSX的基本语法和XML语法相同,都是使用成对的标签构成一个树状结构的数据
- 标签类型
- DOM类型的标签(div、 span等),首字母必须小写
- React组件类型的标签,组件名称的首字母必须大写;二者可以互相嵌套使用
- React 通过首字母的大小写判断渲染的是一个DOM类型的标签还是一个React组件类型的标签
- JSX中使用JavaScript表达式需要将表达式用大括号“{}”包起来
- JSX中只能使用JavaScript表达式,而不能使用多行JavaScript 语句
- 可以使用三元运算符或逻辑与(&&)运算符代替if语 句的作用
- JSX的优点
- 快,执行速度更快,因为它在编译为JavaScript代码后进行了优化
- 可以使用熟悉的语法仿照HTML来定义虚拟DOM。从而编写模板更加简单快速
标签属性
- class 要写成className
- class是JavaScript的关键 字,所以改成className
- 事件属性名采用驼峰 格式,例如onclick 要写成 onClick
- React对DOM标签支持的事件重新做了封装, 封装时采用了更常用的驼峰命名法命名事件
- htmlFor 代替 for属性
- 当JSX标签是React组件类型时,可以任意自定义标签的属性名
- 不能传递 key属性
const element = (
<div>
<h1>Hello, world!</h1>
</div>
)
// 错误的语法
const element = <MyComponent foo={const val = 1 + 2; return val; } />
const element = (
<>
{
if(complete){
return <CompletedList />;
}
else{
return null
}
}
</>
)
// 组件自定义属性
<User name='React' age='4' address='America' />
a标签安全链接
rel=”noopener noreferrer”
<Menu>
<Menu.Item>
<a
rel="noopener noreferrer"
href={null}
onClick={onDelete}
>删除</a>
</Menu.Item>
</Menu>
// Button a标签新窗口打开
<Button
type="link"
href="/list"
target="_blank"
rel="noopener noreferrer"
>
新增
</Button>
<a
href="https://www.google.com/search?q=antd"
target="_blank"
rel="noopener noreferrer"
>
新增
</a>
jsx的本质是什么
- React.createElement()
- 组件 & 标签
- 属性
- 子元素
- 组件名大写,html标签小写
- JSX语法只是 React.createElement (component, props, …children)的语法糖
- 所有的JSX 语法最终都会被转换成对这个方法的调用
- jsx创建界面元素更加清晰简洁, 在项目使用中应该首选JSX语法 ```jsx React.createElement(List, { list: list })
React.createElement(‘ul’, null, list.map((item, index) => { return React.createElement(‘li’, { key: item.id }, item.title) }))
<a name="a21AE"></a>
## jsx渲染
1. 变量 & 表达式
2. if-else语句
3. 三元运算 ternary operator
4. 逻辑 &&
5. switch case
6. 枚举 enums
7. 多层条件渲染 multi-level conditional reandering
8. 高阶组件
<a name="pKdYZ"></a>
## jsx多个属性
1. 把多个属性声明成一个对象,用 ... 展开运算符添加到标签或组件上
```jsx
const attrs = {
href: 'http://example.org',
target: '_blank',
};
<a {...attrs}>Hello</a>
// 等价于
const attrs = {
href: 'http://example.org',
target: '_blank',
};
<a href={attrs.href} target={attrs.target}>Hello</a>
props.children
this.props.children
属性。表示组件的所有子节点React.Children
来处理this.props.children
React.Children.map
来遍历子节点- 不用担心
this.props.children
的数据类型是 undefined 还是 object<App>
<Link>UI</Link> // 在 App组件中可以通过 this.props.children来获取 Link
</App>
jsx常见错误
函数作为React子组件无效
- Warning: Functions are not valid as a React child. This may happen if you return a Component instead of
from render. Or maybe you meant to call this function rather than return it. - 方法(函数)作为一个React子组件是无效的,出现这种情况可能是因为:
- 你return一个组件时,错写成Component而不是写成
- 或许你想调用这个函数而不是 return
- 你return一个组件时,错写成Component而不是写成
- 解决:如果是对象格式,值不能是函数,必须是个React组件
const footer = {
action: () => <View />, // 报错
action: <View /> // 正确的写法是组件
}
render错误
- react-dom.development.js:14815 Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.