深入React DOM对象
DOM事件监听器
React做的工作
- React实现了一个合成事件系统,为应用程序和界面带来了一致性和高性能
- 通过标准化事件来实现一致性,使得事件在不同浏览器和平台间都能拥有相同的属性
- 自动事件委托。 React不会将事件处理程序附加到节点本身,会将单独事件监听器附加到文档根节点,当事件被触发后react将它映射到适当的组件元素,当组件被卸载时,React会自动移除对应的事件监听器。
- 通过JSX语法,回调函数的作用域是组件。会智能第使用事件委托并自动管理卸载。
- 在React中,属性采用了驼峰式大小写规则(例如onClick而非onclick)
DOM API 缺点(例如 onclick,onfocus)
- 会污染全局作用域
- 难以追踪大HTML文件的上下文
- 可能会很慢。导致内存泄漏
JSX和HTML的差别
- 标签特性采用驼峰式大小写风格
- 所有元素都必须闭合
- 特性名称基于DOM API而非HTML语言规范
JSX的怪异之处
- 单一根节点 :React 组件只能渲染一个根节点,即js特性体现,一条返回语句只能返回单个值
- JSX中不能使用条件语句,但是可以使用三元表达式
- JSX在行之间不会生成空格,想要显式地插入一个空格,可以使用包含一个空格字符串{“ ”}的表达式
- JSX不支持HTML注释(例如
<!--comment-->
),可以使用/***/ JS
的注释方式来注释 - 渲染动态HTML,React内置了XSS攻击保护措施。在默认的情况下,不允许动态生成HTML标签并附加到JSX中。React提供了dangerouslySetInnnerHTML属性来跳过XSS保护并直接渲染任何内容。
2.7 幕后的虚拟DOM
- React的关键设计决策是让API看起来像是要在每次更新时都重新渲染整个应用程序。
- DOM操作是一个耗时的任务,所以为了提高性能,React实现了一个虚拟DOM
React并没有在应用程序状态每一次发生变化是都更新真实的DOM,而是创造了一个虚拟DOM
- 在比较DOM树中的节点时,如果节点类型不同(例如
<div>--> <span>
),React就会把它们视为两个不同的子树,丢弃第一个,构建并插入第二个 - 自定义组件也会采用相同的逻辑,如果它们类型不同,React不会去尝试匹配它们的渲染内容,而将第一个从DOM中去除并插入第二个。
如果节点属于同一类型,React可能会采取两种方法来进行处理
- 如果是一个DOM元素(例如
<div id="before"/>
改为<div id="after"/>
),React将只修改特性和样式(而不是替换元素树) - 如果是一个自定义组件(例如将
<Contact details={false}/>
改为<Contact details=true/>
),React不会替换该组件,而是会将新属性发送给当前挂载的组件,最终在组件上触发一次新的render()
方法,这一个过程还会使用新结果重新进行初始化。
- 如果是一个DOM元素(例如
key
属性- React引入
key
特性,key
是一个唯一标识符。允许你在需要进行插入、删除、替换和移动时快速查找元素。每次在循环中创建一个组件是,最好能为每一个子元素都提供一个key
,这样就能帮助React库进行匹配而又能避免性能瓶颈了
- React引入
refs
- 在React中,渲染组件是,与你打交道的总是虚拟DOM,你完全不需要去接触真实DOM
- 在你很有必要操作真实DOM的时候,React提供了一个后门,即
refs
refs
可以像字符串属性那样用于任何组件,例如<input ref="myInput"/>
- 然后就可以通过
this.refs
来访问被引用的DOM标记,例如
let input =this.refs.myInput;
let inputValue=input.value;
let inputRect = input.getBoudingClientRect();
- 在比较DOM树中的节点时,如果节点类型不同(例如