围绕 React 衍生出的思考

声名式开发

不同于原生 JS 的 命令式开发 , React 是声名式开发
命令式开发 更关注 DOM 的每一步挂载,而 声名式开发 更在意数据的改变,只操作 数据,不关心 具体要如何 操作 DOM,改变数据以后 React 会自动帮你完成 DOM 挂载等步骤。

帮助理解

命令式:操作 DOM 使用 JS 去找到需要操作的 DOM 节点,然后 操作它。
声明式:编码好 数据 与 界面的 关系,只操作 数据,不关心 具体要如何 操作 DOM ,把 DOM 都交给 React。


可以与其他框架并存

React可以与其他框架并存,也就是说public文件夹下index.html内的不同节点可以被不同的库所管理。(vue、jQuery等)
每一个库只管理自己对应的DOM,只要不影响外部DOM节点即可

例子

在src文件夹下的index.js中我们将一个 由React管理的组件 挂载在index.html的DOM节点root上:
index.js

在public文件夹下的index.html中我们可以放入由不同库进行管理的DOM节点
index.html


组件化

使用class定义一个组件名继承自react的Component来自定义组件。
自定义组件命名以大写字母开头,调用形式类似h5标签(比如<TodoItem />)。
父子组件的通信

  1. 父组件通过(子组件的)属性向子组件传值(数据或方法)。
  2. 子组件想修改父组件数据的步骤:首先需要父组件向子组件传递一个方法,然后子组件通过调用该方法间接的操作父组件的数据。

面试常问:React中如何做父子组件的通信

父组件向子组件传值(数据或方法):父组件通过在子组件上添加属性的方式将数据(或方法)传给子组件(属性名是自定义的,属性值为需要传递的数据)
子组件内使用父组件数据:在子组件内需要使用父组件传递过来的数据的位置通过{this.props.属性名}来接受对应属性值(数据)。

子组件内修改父组件的数据(子组件向父组件传值):首先需要父组件向子组件传递一个方法,然后子组件通过调用该方法间接的操作父组件的数据。(子组件向父组件传的值可以通过调用父组件传过来的方法的参数传回去)

更多细节和注意事项以及例子可以看详细笔记


单向数据流

在React中只允许父组件向子组件传值,在子组件可以使用父组件传过来的值,但不能在子组件中直接去修改父组件传过来的值。但是子组件可以通过调用父组件穿过来的方法间接的操作父组件的数据。

好处
对代码调试很友好,一旦父组件的某个数据出现问题,所有对该数据的操作都是集中在父组件的某个方法中的,不会涉及到多个子组件身上。

例子

完整例子

删除功能实际上就是想办法在子组件中修改父组件的list数据
父组件
正确的思路是 父组件是将item和index以及删除的方法handleItemDelete(在父组件的handleItemDelete()中进行list数据的删除)传给子组件TodoItem,然后子组件通过调用父组件的方法对list数据进行删除:
正确的父组件
正确的子组件

错误的思路:在父组件中将list数据传到子组件中并在子组件中直接进行修改:
错误的父组件
错误的子组件
报错


视图层框架

React并未把自己定位为大型框架,它只是一个视图层框架,只帮助我们解决数据和渲染之间的问题,至于组件之间怎么传值它并不负责
在小型项目中光是依靠React来进行传值也是可以的(比如之前的TodoList,只有两层组件)。但在大型项目时,光用 React 是不够的,必须结合一些数据层框架(比如redux),解决复杂传值的问题。

例子

在一个大型项目中,组件之间呈树状分布,如果React去负责组件之间的传值将非常困难,假设我们紫色的组件想传值给最顶上的组件,就需要层层传递,非常复杂:
各个组件树状图


函数式编程

例子:在React中我们使用的是一块一块的函数,比如TodoList.js中的constructor构造函数、render函数、getTodoItem函数等等:
TodoList.js中

好处:给前端自动化测试带来很大便捷性。只需要给函数一个输入值,看看函数输出的时候符合预期即可。


,