react设计模式与最佳实践 读书笔记

作者【意】米凯莱·贝尔托利 译者:林昊 阅读时间:2021.01.28 ~

  1. 关注点分离 2.React 声明式编程范式
    • 命令式编程描述代码如何工作,而声明式编程则表明想要实现什么目的
    • 声明式编程无需使用变量,也不用在执行过程中持续更新变量的值
    • 使用声明式编程编程人员只需描述他们想要实现什么目的,而无需列出实现效果的所有步骤,最终代码会更简单,bug也会更少,可维护性会更强。
  2. 一致性比较:react调用组件时通过传入props来取回底层元素,再对返回结果递归的执行相同操作,直到取到完整的DOM节点数,将它渲染到屏幕上。
  • 组件:元素的type是函数
  • DOM节点:元素的type是字符串。
  1. React最终目标:将创建组件所用到的每项技术都封装起来,并根据它们的领域和功能进行关注点分离。

  2. React是个很小的库,分成了两个包:

  • React: 实现了react库的核心特性(可以支持不同的目标平台:浏览器的React Dom、移动设备上的React Native)
  • react-dom:包含了与浏览器相关的所有特性。
  • 只引入核心包,则无法使用JSX语法,因为JSX不是浏览器支持的标准语言 (简单UI可使用createElement,复杂的就建议引入JSX转译器了)
  • 如果应用较大,建议引入路由库来处理不同的页面和视图
  • 应用扩增,需要利用外部依赖项对复杂操作进行抽象,此时应该引入“包管理器”
  • 如果需要将应用拆分成独立的模块并按正确的形式组织文件,则应考虑使用模块打包器。
  • 上述通过迭代增多项目依赖内容的方式,可避免学习新内容时的“疲劳感”

第二章 整理代码

JSX

  1. JSX react提供了两种定义元素的方式:一种是使用JavaScript函数,另一种是使用类似xml的jsx语法
  2. babel: 用来转义jsx和es2015(es6)后的语法(主流浏览器已经很好的支持了es2015,但更新的语法及特性支持程度不一,所以把js相关代码统一转译成es2015的版本后再执行)
  • npm i --global babel-cli
  • babel source.js -o output.js
  • npm i --global babel-preset-es2015 babel-preset-react // 产入产出的预设方案
  • 运行babel会把jsx 语法的

    转换成 React.createElement('div')

  1. jsx创建html元素时以小写开头
  2. jsx与html的区别
  • 保留字取代 className=class , htmlFor = for
  • 样式 样式名写法由css字符串改为了驼峰式命名法
  • 根元素 jsx会转换成JavaScript函数,而JavaScript函数不允许返回两个函数,因此多个同级元素必须封装在同一个父元素里
  • 空格 html中标签换行会有空格,jsx没有
  • 布尔值属性 jsx:声明即为true,html声明未赋值即为false
  1. 展开属性 来源于ecmaScript提案中的 对象剩余/展开属性(Object Rest/Spread Properties for ECMAScript)
  2. 向子元素传递数据时,不要按引用方式传递整个JavaScript对象,而要使用对象的基本类型值以方便校验,能够bug更少、更稳健。

Eslint

https://www.cnblogs.com/keepLeung/p/14363301.html

函数式编程基础

  1. 是一种声明式范式,避免代码副作用,推崇数据不可变,从而更易维护,可使代码更整洁
  2. 一等对象:可以赋值给变量,可以作为参数传给其他函数
  3. 高阶函数:接受一个函数作为参数(也可以是其他参数),通常添加一些增强的特殊行为,而后返回另一个函数作为返回值
  4. 纯函数:不产生副作用,也就是说他不会改变自身作用域以外的东西
    // 纯函数


    const add = (x,y)=>x+y


    // 非纯函数


    let x = 0;


    const add1 = y => {x = x+y}


    // 如果纯函数需要改变作用域以外的东西,可以通过返回值进行


    let x = 0;


    x = add(x,y)


  5. 不可变性(一种操作数据的方式):函数式编程中,函数不会修改变量值,而是创建新的变量,赋值后再返回
    // 未遵循不可变性


    const add = arr=>arr.push(3)


    const arr = [1,2]


    add(arr) // [1,2,3]


    add(arr) // [1,2,3,3]


    // 遵循不可变性


    const add = arr=>arr.concat(3)


    const arr = [1,2]


    const result1 = add(arr) // [1,2,3]


    const result2 = add(arr) // [1,2,3]


  6. 柯里化:将多参数函数转化为单参数函数,同时这些单参数函数的返回值也是函数
    // 不柯里化


    const add = (x,y)=>x+y;


    // 柯里化


    const add = x=>y=>x+y;


  7. 组合:多个易于测试的纯函数、组件组合成一个 可以提供更高级功能的新函数
    const add = (x,y)=>x+y;


    const squre = x =>x*x;


    const addAndSqure = (x,y)=>squre(add(x,y))


  8. 幂等函数: 传入相同的应用状态时返回同样的UI

第三章 开发真正可复用的组件

  1. 箭头函数会自动绑定this
  2. 用新状态调用setState时,对象会合并到当前状态上。
this.state={a:1}


this.setState({


b:2


})


// 最终的状态


{a:1,b:2}


应将setState看作异步的

  1. react知道如何优化事件处理器内部的状态更新,但无法优化执行过程:正常顺序取到旧值,setTimeout里取到新值
  2. React lumberjack用于调试应用的某个特殊状态
  <script src="https;//unpkg.com/react-lumberjack@1.0.0"><script>


Lumberjack.back()


Lumberjack.forward()


  1. 只能将满足需求的最少数据放到状态中;触发事件时只应将需要更新的值添加到状态中
  2. 多个组件都需要使用同一份信息,应考虑使用应用层级的状态管理器,如redux
  3. 应避免使用状态的情况:
    • 可派生的值(可通过props计算得到)
    • 渲染方法
  4. props 可使用propTypes验证参数类型(只在开发模式下有效),更像ts,定义参数类型明确的接口
    Button.propTypes = {


text: React.PropTypes.string.isRequired


}


  1. React Docgen 可配合propTypes生成文档
  2. 考虑多抽象一层以提高组件的可复用性
  3. storybook:已有组件列表服务

第四章 组合一切

  1. children的propTypes是array,如果只有一个的话会被优化成element
  2. 容器组件与表现组件模式,更清晰、更易维护。表现组件一般只包含ui,通常写为无状态的函数式组件
  3. mixin(已废弃)
    • 解决的问题:不同组件共享功能
    • 缺点:mixin内部函数不清楚,可维护性差;多个mixin定义或调用同一个函数型、状态中使用了属性名,会冲突;mixin相互依赖会导致耦合度增加、拓展困难
  4. 高阶组件(命名规范建议以with开头),将需要复用的部分作为被包裹组件的props传入,不影响被包裹组件的复用性。高阶组件不可滥用,每一层高阶组件都在添加新的渲染函数、生命周期方法、内存分配
  5. recompose(一个提供了许多高阶组件的库):flattenProp\renameProp\compose\getContext
  6. context:在组件树中传递数据
    • 为避免组件context api与组件产生耦合,应使用高阶组件从context中获取数据,转换成props后再传递给组件
  7. 函数子组件,可动态的组合组件。优点如下:
    • 可复用程度高,不需要关系子组件要接收什么
    • 可以像高阶组件一样封装组件,但属性不需要固定,开发者可自行决定函数接收的变量名称
    const Name = ({children})=>children('World')


    Name.propTypes = {


    children : React.PropTypes.func.isRequired,


    }


    // 调用Name


    <Name>


    {name=><div>Hello,{name}!</div>}


    </Name>


第八章 服务端渲染(SSR, server-side rendering)的乐趣与益处

  1. 通用应用是什么? 应用的代码可以同时用于服务器和客户端

同构应用 :指应用在服务端和客户端看起来一模一样

  1. 启用服务器渲染的理由

  2. 用React创建简单的静态服务端渲染应用

  3. 了解服务端渲染的数据获取方式,并理解脱离和注回等概念

  4. 用Zeit开发的next.js 可以轻松创建同时在服务端和客户端运行的React应用

问题:

  • 服务器渲染(可以开发通用应用)?

第十二章 未来的行动

  1. 为React做贡献
    • 创建一个简单的示例 通过jsfiddl
    • 提交问题 repoxx/issues/new
    • fork整个仓库,编写代码解决问题,为补丁编写全面的测试,通过原有所有测试,避免引入新问题
    • 发起pull request
  2. 开源的好处
    • 他人可以受益,避免重复开发
    • 可以提升自己的开发技能,遵循最佳实践
    • 获得很多启发,他人思考的角度,甚至被帮助完善你的软件
    • 获得与志同道合之人交流的机会
  3. 测试的重要性
    • 代码更文件
    • 帮助他人理解代码功能
    • 有助于发现新增代码的缺陷
    • 让参与编写代码的其他人员更有信心
  4. readme、lecense、react Storybook(文档)、示例都应该有
  5. 尽可能的减少样式、避免class、id名与实际项目冲突