React引入虚拟DOM,状态,单项数据流等设计理念,
形成以组件为核心,利用组件搭建UI的开发方式,将数据,组件状态和UI映射在一起

  • 一个组件对应一个功能,单一职责
  • map循环列表时,必须添加 key属性,且 key属性不能是 undefined
  • state是异步的,我们所做的任何修改不会立即生效,并且可能会在下一次渲染时生效
  • 组件名称,必须是大驼峰命名,组件必须以大写字母开头

React 八种条件渲染,
React不同条件渲染出不同效果
https://www.jianshu.com/p/629234e7c63a
https://zhuanlan.zhihu.com/p/38220426
https://blog.logrocket.com/conditional-rendering-in-react-c6b0e5af381e/
http://www.voycn.com/article/yi-zaireactzhongshixiantiaojianxuanrande7zhongfangfa
https://blog.csdn.net/iceking66/article/details/80649140
https://blog.csdn.net/weixin_33774615/article/details/87946811

jsx不同的渲染

  1. if语句
  2. 三元运算 ternary operator
  3. 逻辑 &&
  4. switch case
  5. 枚举 enums
  6. 多层条件渲染 multi-level conditional reandering
  7. 高阶组件

if语句

如果没有data没有数据,可以提前return
组件如果return null, 将不会被渲染出来

  1. function App({dataSource}) {
  2. // 阻止组件渲染
  3. if (!Array.isArray(dataSource)) return null
  4. if (!dataSource.length) return <Empty /> // antd的 Empty组件
  5. return (
  6. <>{data.map(item => <ListItem data={data} />)}</>
  7. )
  8. }

三元运算 ternary operator

三元运算符来代替if…else… 条件渲染
三元运算的条件渲染更加的简洁

  1. function App({data, mode}) {
  2. if (!Array.isArray(data)) return null
  3. if (!data.length) return <Empty /> // antd的 Empty组件
  4. return (
  5. <>
  6. {
  7. (mode === 'edit')
  8. ? <ListItem data={data} />
  9. : <ListEdit data={data} />
  10. }
  11. </>
  12. )
  13. }
  14. // a ? b : c 三元运算
  15. <div style={{ display: (this.state.status === 1) ? 'none' : 'block' }} >

逻辑 &&

当你想渲染一个组件或者什么也不渲染的场景
用 && 可以使返回 null 的情况的条件渲染更加的简洁,

  • 缺点:如果 data是 0,就会显示 0

    1. function List({data}) {
    2. return (
    3. <>
    4. {
    5. data && <ListItem data={data} />
    6. }
    7. </>
    8. )
    9. }

switch case

  1. 多种条件渲染的情况,例如依据不同的state渲染不同的Component
  2. 多种条件中渲染最好的方式是枚举
  3. switch…case语句,永远要加上default情况,因为React组件要么返回元素,要么返回null
  4. 如果组件依据 state 属性渲染时,最后添加上 PropTypes验证
  5. 将条件渲染结果内联在switch…case中的方法是,使用立即调用函数 ```jsx Notification.propTypes = { text: PropTypes.string, state: PropTypes.oneOf([‘info’, ‘warning’, ‘error’]) }

function Notification({ text, state }) { switch (state) { case ‘warning’: return case ‘error’: return default: return } }

// 内联 switch case function Notification({ text, state }) { return ( <> {(() => { switch (state) { case ‘info’: return ; case ‘warning’: return ; case ‘info’: return ; default: return null; } })()} </>
) }

  1. <a name="t8q05"></a>
  2. ### 枚举 enums
  3. 多种条件中渲染最好的方式是**枚举**
  4. <a name="u3zSk"></a>
  5. ### 多层条件渲染 multi-level conditional reandering
  6. <br />
  7. <a name="47MyS"></a>
  8. ## UI视图的本质
  9. 1. 渲染逻辑与 UI视图表现的内在统一
  10. 2. react没有采取 html与 js分离的原则,对这两部分进行了组合
  11. 3. react把 HTML与渲染逻辑进行了耦合,就形成了 jsx
  12. <a name="FTDnX"></a>
  13. ### jsx的特点
  14. 1. 常规的 html或 js代码都可以与 jsx兼容
  15. 2. 可以在 js中嵌入表达式,语法上更贴近 js
  16. 3. 使用 jsx指定子元素
  17. 1. 可以使用 /> 来闭合标签,就像 HTML5的单标签一样
  18. 2. 也可以包含很多子元素
  19. 4. jsx命名使用小驼峰命名,camelCase
  20. 1. class,要写成 className
  21. 2. for,要写成 htmlFord等
  22. 5. 自定义 jsx属性,要使用 data-开头
  23. 6. jsx最终会编译为 React.createElement() 对象
  24. 1. 2种写法,完全相同的结果
  25. 2. 1:是 jsx语法;2 是原生的 js代码
  26. 3. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/112859/1613015704904-bdf5ff57-a45e-465c-9e20-daa1745534d5.png#averageHue=%23272932&height=136&id=bl2Hd&originHeight=272&originWidth=1452&originalType=binary&ratio=1&rotation=0&showTitle=false&size=213305&status=done&style=none&title=&width=726)
  27. ```jsx
  28. <Logo src="./images/logo.jpg" />
  29. const Menu = (
  30. <Menu>
  31. <Menu.Item>UI</Menu.Item>
  32. <Menu.Item>Web</Menu.Item>
  33. </Menu>
  34. )
  35. // 小驼峰命名, data-属性
  36. const element = <div className="title" tabIndex={1} data-index="10"/>

文件后缀用 .jsx 还是 .js

  1. jsx不是标准的 js语法
  2. 推荐在 .js文件里面使用标准的 js语法
  3. 在 react语法中使用 .jsx文件,区分更直观一些
    1. react并不强制使用 jsx,可以使用原生的 js
  4. 总结:使用 .jsx 或 .js都可以,因为主流编辑器都可以识别这两种文件

jsx key值

  1. 不能用 Math.random() 作为 key
  2. 不推荐使用 index作为 key
    1. 因为一旦列表的数据重排,数据索引也会发生变化,不利于渲染优化
  3. 建议给 key一个固定的唯一值
  4. key不能重复,key的唯一性仅限于当前的列表;不是全局的唯一

Form 动态 key

  1. Form表单Bug,删除,永远只删除最后一项
  2. react 表单项动态删除,删掉的都是最后一个,因为 你用了 index作为 key
    1. react 删除数据永远都是从最后面删除
    2. 在遍历后,不要把index用于元素个项的识别上,例如:key name等
    3. 假设 你的key设置为map中的索引,假设为0,1,2(原dom树),现在你用splice删除掉1,重新渲染时,还是会按map索引按顺序渲染为0,1(新dom树),由于react渲染机制是比较的key值,发现key(0,1)都没变,所以保留原dom树的0,1元素(包括里面内容都不变),而由于数量少了一个,渲染的最后一个就没有渲染,就感觉是删除的最后一个。
  3. 你要分页渲染一个列表,每次点击翻页会重新渲染,使用唯一id作为 key
    1. 翻页后,三条记录的key和组件都发生了改变,因此三个子组件都会被卸载然后重新渲染

input输入一下卡顿一下,需要点击才能输入

  1. React中的 diff算法,通过 key值判断,前后虚拟DOM是否发生变化
  2. 用动态输入的值作为 key,每次都会重新 renderDOM,引起重绘
  3. 不能用输入的值,或 Math.random或时间戳作为 key

image.png

渲染 html

  1. const createMarkup = (body) => {
  2. return { __html: body };
  3. }
  4. <div dangerouslySetInnerHTML={createMarkup(markdownHtml)} />
  • 组件声明
    • 始终声明 PropTypes
    • Props 非空检测
    • 使用 Props 初始化
  • 计算属性
  • 事件回调命名
  • 组件化优于多层 render
    • 纯函数的 render]
  • 状态上移优于公共方法
  • 容器组件
  • classnames

始终声明 PropTypes

https://www.jb51.net/article/122796.htm
https://www.wenjiangs.com/doc/itn09qbji

Props验证对于组件的正确使用是一种非常有用的方式
可以避免随着你的应用的程序越来越复杂从而出现很多的bug和问题。并且,它还可以是你的程序变得更易读

每一个组件都声明 PropTypes,非必须的 props 应提供默认值
人知的 props 如 children, dispatch 也不应该忽略
如果一个组件没有声明 dispatch 的 props,那么一眼就可以知道该组件没有修改 store 了

Props 初始化

http://shripadk.github.io/react/tips/props-in-getInitialState-as-anti-pattern.html
https://blog.csdn.net/sinat_17775997/article/details/59021696

除非 props 的命名明确指出了意图,否则不该使用 props 来初始化 state

  1. // good
  2. constructor (props) {
  3. this.state = {
  4. items: props.initialItems
  5. }
  6. }
  7. // bad
  8. constructor (props) {
  9. this.state = {
  10. items: props.items
  11. }
  12. }

如果在开发一系列会 dispatch 的组件时,可在这些组件的目录建立单独的 .eslintrc 来只忽略 dispatch

  1. App.propTypes = {
  2. value: PropTypes.array.isRequired,
  3. onChange: PropTypes.func.isRequired
  4. }
  5. function App() {
  6. }

defaultProps

对于并非 isRequired 的 proptype,必须对应设置 defaultProps,避免再增加 if 分支带来的负担
如有必要,使用 PropTypes.shape 明确指定需要的属性

  1. // good
  2. class MyComponent extends Component {
  3. render() {
  4. return <div>{this.props.person.firstName}</div>
  5. }
  6. }
  7. MyComponent.defaultProps = {
  8. person: {
  9. firstName: 'Guest'
  10. }
  11. }
  12. // bad
  13. render () {
  14. if (this.props.person) {
  15. return <div>{this.props.person.firstName}</div>
  16. } else {
  17. return <div>Guest</div>
  18. }
  19. }
  20. Prop Validation

classnames

使用 classNames 来组合,多个 class

  1. // good
  2. render () {
  3. const classes = {
  4. selected: true,
  5. menu: true,
  6. active: this.props.display
  7. }
  8. return <div className={classnames(classes)} />
  9. }
  10. // bad 字符串拼接
  11. render () {
  12. return <div className={'menu ' + this.props.display ? 'active' : ''} />
  13. }

纯函数的渲染

render 函数应该是一个纯函数
stateless component 无状态也是
不依赖 this.state、this.props 以外的变量,也不改变外部状态
减少 window. 全局属性的使用

数组遍历,map,必须要用 key属性
在一个函数里面,改变传入的对象本身是不好的写法

  1. // bad
  2. render () {
  3. return <div>{window.navigator.userAgent}</div>
  4. }
  5. // good
  6. render () {
  7. return <div>{this.props.userAgent}</div>
  8. }