HTML DOM结点与React DOM
一个HTML DOM结点对于React来说是“根”DOM结点,关于该节点的所有内容都由React DOM管理。
在.js
文件中利用React
语法生成各种元素、组件,而后通过ReactDOM.render(待渲染的元素或组件, 利用普通DOM获得HTML中的节点)
渲染到HTML中对应的根DOM节点中。
利用React DOM的优点是它只将元素和它的子元素与它们之前的状态比较,只进行必要的更新来达到预期状态。
元素
React元素既可以是原HTML文件中的DOM标签及其组合,也可以是用户自定义的组件。
const element = DOM-tag-or-self-defined-component
组件
组件名称必须大写字母开头。
一般组件
函数组件:本质是编写JavaScript函数。
1 | function Toppercase(props){ |
class
组件
1 | class Toppercase extends React.Component{ |
组合组件
(更高一层级/更偏向用户层的)组件可以在其输出中引用其他(更低一层级/实现功能更单一的)组件。
一般来说,每个新的React应用程序的顶层组件都是App
组件。
如何抽取组件
元素的声明可以包含不止一个HTML结点(当然这是被允许的JSX写法),将元素抽取出来利用组件重新声明。
在被抽取出来的部分需要利用props
对象在组件内部访问组件本身的属性、子组件及其属性;在更高层次的组件内部使用较低层次的组件,使用大写的单闭合的标签来标明属性及其取值。
这是属于外观的封装。
组件内部属性访问
props
当React元素为用户自定义组件时,它会将JSX所接收的属性attributes以及子组件children转换为单个对象传递给组件,这个对象被称为props。
要在更高层级更抽象的组件层次访问更低层次更具体的组件层次,需要使用点访问,props.children.child-attribute
或props.attribute
。
props
具有只读性,组件不能修改自身的props
。因为这是静态的,不可更改的,后面需要在组件中引入state
来实现组件自我更新。
state
1、只能在构造函数中对this.state=
使用赋值语句。
2、为了达成更改state且重新渲染组件的目的,需要使用setState()
。
3、this.state
与this.props
的更新可能是异步的,不要利用这两个值来更新下一个状态。应当将他们作为函数的参数传入,在函数体内更新。
4、 当state包含多个属性时,单独更新其中某一个属性的值时,setState()
会自动将更新的state合并到当前没有更改的state。
state与props的关系
自上而下的单项数据流决定了:
任何state只属于拥有并设置了它的组件,是局部的、封装的。
某一组件可以将state作为props向下传递给它的子组件。
将函数组件转换成class组件
为什么需要从函数组件转换到class组件
每次组件更新时都有实例中的render()
被调用。
让ReactDOM
渲染DOM节点的时候,只有一个此组件的实例被创建,关于这个实例可以使用state
或生命周期方法。
步骤
1、同名class且继承与React.Component
2、类体添加render()
方法并将函数体放入其中
3、函数体中的this.props
替换props
4、删除剩余的空函数声明
在class组件中添加并使用state
1、将需要做出变化的属性从props
的点访问转移到state
的点访问。
2、添加class
构造函数,为this.state
赋初始值,且通过super(props)
传递到父类的构造函数中。
在class组件中添加并使用生命周期方法
目的是在组件被销毁时释放资源。
当组件第一次被渲染到DOM的时候,设置一个“挂载”(mount)。componentDidMount(){}
。
当组件被删除的时候,设置一个“卸载”(unmount)。componentWillUnmount(){}
。
class组件关于state和生命周期的调用顺序
组件被传递给ReactDOM.render()
,对应到匹配的根节点DOM,进入组件。
React会调用该组件的构造函数,对象初始化。
React会调用该组件的render()
方法,确定在html页面上要展示什么,更新根节点DOM来匹配组件输出。
一旦组件的初始输出被插入到根节点DOM中后,React调用组件中挂载的生命周期方法。
生命周期方法或其调用的其他方法会涉及setstate()
方法,由此React知道了state已经改变,重新调用render()
确定页面显示内容,从而渲染更新根节点DOM。
一旦组件从DOM中被移除,React调用卸载的生命周期方法。
列表组件与key
在一个组件中渲染列表,通常可以对数组进行调用arr.map( arrow-function)
。箭头函数执行将数组转化为列表元素(list item)的功能。
当我们创建一个列表元素(list item)时,我们必须给每一个列表元素指定一个key
属性,即<li key={}> {JS-expression} </li>
。
key
key 帮助 React 识别哪些元素改变了,比如被添加或删除。
key是传递给React的,而不是传递给组件的,即不能用props.key
来获取key属性的值。可以另外引入一个别名属性如id,其属性值与key属性值相同,可以被组件利用props.id
读出。
一般使用数据中的id(data.id
)来作为元素的key,不到万不得已使用元素索引。
key不一定要全局唯一,但是在其兄弟节点之间独一无二。
当把单个列表元素作为函数组件提取出来的时候,应该在哪里设置key?经验总是:在map()
方法中的元素设置key。
受控组件与表单
为什么需要受控组件
HTML表单元素的工作方式与其他DOM元素不一样。表单元素如<input>
,<textarea>
,<select>
通常会维护一个属于自己的“state”,根据用户输入自动进行UI上的更新。
React中,组件的state属性控制着可变状态(mutable state),并且只能通过setState()
来更新。
需要让这两个state建立依赖关系统一起来——让React组件的state称为唯一的数据源,并让组件能够控制用户输入过程中表单发生的操作。
被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
受控组件的建立
分为两个步骤
1、 将React
里的state
属性和表单元素的值建立依赖关系。
也就是让组件获得对表单元素输入框内容的控制权。输入框的内容取决于元素的value
属性,将表单元素的value
属性赋值为this.state.value-of-element
。
此时,表单元素内容是只读的,用户输入新的内容并不会让组件的state有所变化。此时运行会给出警告:
Warning: Failed prop type: You provided a
value
prop to a form field without anonChange
handler. This will render a read-only field. If the field should be mutable usedefaultValue
. Otherwise, set eitheronChange
orreadOnly
.
2、 通过onChange
事件与setState()
结合更新state
属性
用一个事件来监听输入内容的改变,在回调函数中利用this.setState
更新表单元素的value
属性。
组件间的数据共享
多个组件需要反应相同的数据变化时,需要把共享状态提升到共同父组件中去,让父组件中共享的state称为多个子组件的唯一的数据源。实现自上而下的数据流。
一般在一个组件内部变化的数据通过state来访问或控制,多个组件在个字内部的state中相互独立地保存着各自的数据。
操作步骤
第一步,需要夺取子组件对共享数据的控制权,包括初始赋值与变化赋值。其思想与受控组件相同。
将想要共享的数据从由子组件内部state访问变成由父组件props传入,即由this.state.shared-data
变为this.props.shared-data
。
当我们需要子组件相应来自父组件的数据改变时,不再使用this.setState()
,而是调用this.props.shared-data-change-function
,获取父组件中具体的值,这个值就是一个事件处理函数。
第二步,相应改变父组件。
需要在父组件中构造函数中把this.state
设置为想要共享的数据。
在父组件中提供子组件相应数据更改的函数,并作为属性值传入子组件中。
组合
空元素
空元素(empty element)是在HTML中不能存在子节点(例如内嵌的元素或者元素内的文本)的element。
一般的HTML元素的名称是在尖括号中使用的小写名称。例如,<p><\p>
带有一个斜杠开始的结束标记。
在一个空元素上结束标记既不需要也不允许,使用闭合标签是无效的。<input><\input>
是无效的写法,应该使用<input \>
。
组件使用的约定
在组件使用中我们需要注意两点:
1、 必须大写字母开头。这是为了和一般的HTML元素的小写名称加以区别
2、 在使用时没有闭合标签。这样的组件就与之前提到的空元素类似。
第二个注意点不一定是完全成立。当我在组件中包含/嵌套子组件,可以通过带闭合标签的尖括号将子组件传递给组合组件。由此引入组合、props.children
的概念。
组合与props
方式1:
在组件定义中引入{props.children}
。
在组件使用时传入<Component>your-children-Component<\Component>
。
方式2:
在组件定义中引入{props.self-defined-attribute}
。
在组件使用时传入<Component self-defiend-attribute={sub-Component}\>
。
- 本文标题:React的元素、组件与事件处理
- 本文作者:徐徐
- 创建时间:2020-10-05 21:37:31
- 本文链接:https://machacroissant.github.io/2020/10/05/react-learning/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!