React非dom属性介绍
非dom属性?
dangerouslySetInnerHTML,ref,key
非dom标准属性,也就是说dom标准里面没有规定的属性,react引入了三个非dom属性,如上。
dangerouslySetInnerHTML:字面意思,危险的设置内部html,这个属性的作用就是在jsx中,直接插入html代码。我们为什么用这个属性插入html代码呢?而不是在编写代码的时候直接写入呢?因为有的时候我们在编写代码的时候,无法确实要插入什么代码,也就是说这部分html代码是动态生成的。或者说不是由我们来编写的,为什么这中行为是危险的呢?有一个词语叫做跨站攻击,之所以会产生跨站攻击,就是因为有这样的直接写入代码功能,我们举个例子,如果页面上要显示一个内容,这个内容来自于用户的输入,假设用户的输入中包含了代码,比如说js代码,html代码,如果我们不经过检测就直接使用,把这个dom插入到页面中,那么其他人访问页面的时候,就会执行这个人写入的代码,由于我们无法判断这个用户的意图,所以他有可能写入很危险的代码,比如说添加一个连接,连接到一个木马,那么访问这个页面的用户,就会在不知不觉中中病毒或者下载木马,这是非常危险的,但是有些时候我们确实需要动态的写入代码,所以react还是提供了这个属性,只是明确的在名字里面告诉你这个属性是很危险的,尽量不要去使用。
ref:reference的缩写,父组件引用子组件,我们在编写组件的时候,经常会用到嵌套的情况,父组件如果嵌套了子组件,父组件引用子组件的时候,就需要用ref,在实际的使用中ref其实是在父组件中维护了很多引用,每一个引用都引用到了一个对应的子组件,这样我们在父组件中就可以通过这些引用来操作子组件。为什么我们不能操作父组件的父组件呢?这个其实不是代码问题,而是设计问题,在react中我们使用组件的目的就是使代码模块化,每个组件只需要考虑自己自身的功能,逻辑,不需要关心谁在使用它,因此组件不需要引用他本身的父组件,父组件和组件之间的交互式通过属性的传递来实现的,我们后面会说。但是这样的传递是单向的,也就是说,属性总是由上往下传递,下面的组件不会对上面的组件进行控制,这是为了让逻辑更加清晰,
key:提高渲染性能。react特点之一就是性能好,这是因为他去除了手动的dom操作,完全由自动来实现,但是自动实现就说明他有一套算法,也就说在页面发生变化的时候,react需要应用这套算法来判断如何高效的修改页面,以反映出对应的变化,这个算法通常被称为diff,也就是different的缩写,表示计算两个状态之间的差异。
react diff算法
react diff算法的流程图
首先需要明确我们现在进行比较的是两个组件,react中所有的东西都是组件,所以我们只要明白了两个组件之间是如何比较的,其他的结构都可以分解成组件进行比较。
最左侧是开始,开始以后第一个判断就是节点是否相同,相同的意思就是div和div是相同的,div和p就是不同的,或者说我们自定义的HelloMessage和HelloMessage是相同的,HellowMessage 和HelloWorld就不是相同的组件,节点如果相同才会进行后面的比较,如果节点不同,react会直接抛弃旧的节点,生成一个全新的节点,在这里react是基于一个假设,如果两个节点不同,那么他们的内容很大程度不同。如果节点不同我们就直接结束比较,生成全新的节点,如果节点相同,下一步需要判断的是,这个几点是自定义的节点还是dom的标准节点,也就是说,他是div还是HelloWorld,如果说不是自定义的节点,是标准的节点,那么react下一步需要做的就是比较两个节点的属性,比如说class,id等,如果属性完全相同,就说明两个节点是相同的,结束比较;如果属性不同,就把不同的属性记下来,并应用改动,比如说多了一个新属性,就加入一个新属性,少了一个属性就删掉一个属性,类似这样的操作。也就是react并不会删掉旧的节点,只会在他上面进行操作。若果是自定义的节点,react会重新渲染他,我们后面会学习属性和状态,一个组件有很多状态,如果是同一个自定义组件,那么新组件可能只是旧组件的一个状态,所说reac会 把新的状态传入到旧的组件中,然后比较组件的渲染结果,并进行改动,也就是说react仍然不会重新生成组件,而是在旧的组件上进行改动,这就是diff算法的整个流程。那么key到底有什么用呢?key作用主要体现在节点的比较,假设我们有一个类似列表的节点,也就是父节点里面有多个子节点,那么如果没有key的时候,我们进行改动,react会比较傻的从左到右进行比较,比如说在改动之前只有节点1,在改动之后我们插入一个节点2,变成了节点2,节点1,那么react执行的操作是,删除节点1,添加节点2,添加节点1,也就是说,react无法判断新状态中的节点1是不是就状态中的节点1,所以他只能把不同的全部删掉,即使他们可能相同,这样就导致性能上的问题,那么引入key的目的就是给每个节点加上唯一的标识,这样的话react通过比较key,就可以知道到底哪些节点是原有节点,哪些节点是新加入的节点,针对我们刚才说的例子, 节点1变成了节点2节点1,这时候,react只需要做一个操作,就是插入节点2,因为节点1的key是一样的,说明他们两个是同一个节点,没有变化。
了解这个原理,对于我们编写react组件有什么启示呢?
第一点就是如果两个组件非常类似,那就尽量把他们写成一个组件,因为我们在流程中看到,两个不相同的组件一定会被重新生成,即使他们的内容非常的相似,。第二个启示就是如果使用类似的列表来展示元素的话,那么元素尽量加上key,这样可以极大地提高效率,避免不必要的性能损耗。
如何使用非dom属性?
dangerously的实例
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>hello world</title> </head> <body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var style={ color:"red", border:"1px solid #f09", }; var rawHTML={ __html:"<h1>I am inner HTML</h1>" }; var HelloWorld=React.createClass({ render: function(){ return <p>Hello,world</p> } }); React.render(<div style={style} dangerouslySetInnerHTML={rawHTML}></div>,document.body); </script> </body> </html>
ref实例,要注意通过引用拿到的并不是这个dom节点本身,也就说我们并不能进行dom之间的操作,比如说设置文本,这样是不行的,我们拿到的只是一个虚拟的dom节点,也就是react展示给我们的dom节点,如果想要拿到真正的dom节点,还需要调用一个方法,后面我们会说,不过react并不会鼓励我们这样去做,除非在特殊的情况下,我们需要操作dom节点,其他情况react会帮助我我们进行操作,
这个例子不全,后面我们会继续讲解。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>hello world</title> </head> <body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var style={ color:"red", border:"1px solid #f09", }; var rawHTML={ __html:"<h1>I am inner HTML</h1>" }; var HelloWorld=React.createClass({ render: function(){ this.refs.childp return <p ref="childp">Hello,world</p> } }); React.render(<div style={style} dangerouslySetInnerHTML={rawHTML}></div>,document.body); </script> </body> </html>
key实例:注意在每个组件的内部,key的值必须是不同的,注意是组件内部!两个组件之间就没有这个限制了。
记住两点:1,内容类似的组件尽量合并称为同一个组件,2列表类型的元素,一定要加上唯一的key,做到这两点,就能避免很多性能问题。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>hello world</title> </head> <body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var style={ color:"red", border:"1px solid #f09", }; var rawHTML={ __html:"<h1>I am inner HTML</h1>" }; var HelloWorld=React.createClass({ render: function(){ return <ul> <li key="1">1</li> <li key="2">2</li> <li key="3">3</li> </ul> } }); React.render(<div style={style} dangerouslySetInnerHTML={rawHTML}></div>,document.body); </script> </body> </html>

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

如何利用React和RabbitMQ构建可靠的消息传递应用引言:现代化的应用程序需要支持可靠的消息传递,以实现实时更新和数据同步等功能。React是一种流行的JavaScript库,用于构建用户界面,而RabbitMQ是一种可靠的消息传递中间件。本文将介绍如何结合React和RabbitMQ构建可靠的消息传递应用,并提供具体的代码示例。RabbitMQ概述:

ReactRouter使用指南:如何实现前端路由控制随着单页应用的流行,前端路由成为了一个不可忽视的重要部分。ReactRouter作为React生态系统中最受欢迎的路由库,提供了丰富的功能和易用的API,使得前端路由的实现变得非常简单和灵活。本文将介绍ReactRouter的使用方法,并提供一些具体的代码示例。安装ReactRouter首先,我们需

PHP、Vue和React:如何选择最适合的前端框架?随着互联网技术的不断发展,前端框架在Web开发中起着至关重要的作用。PHP、Vue和React作为三种具有代表性的前端框架,每一种都具有其独特的特点和优势。在选择使用哪种前端框架时,开发人员需要根据项目需求、团队技能和个人偏好做出明智的决策。本文将通过比较PHP、Vue和React这三种前端框架的特点和使

Java框架与React框架的整合:步骤:设置后端Java框架。创建项目结构。配置构建工具。创建React应用。编写RESTAPI端点。配置通信机制。实战案例(SpringBoot+React):Java代码:定义RESTfulAPI控制器。React代码:获取并显示API返回的数据。

如何利用React开发一个响应式的后台管理系统随着互联网的快速发展,越来越多的企业和组织需要一个高效、灵活、易于管理的后台管理系统来处理日常的操作事务。React作为目前最受欢迎的JavaScript库之一,提供了一种简洁、高效和可维护的方式来构建用户界面。本文将介绍如何利用React开发一个响应式的后台管理系统,并给出具体的代码示例。创建React项目首先

Vue.js适合中小型项目和快速迭代,React适用于大型复杂应用。1)Vue.js易于上手,适用于团队经验不足或项目规模较小的情况。2)React的生态系统更丰富,适合有高性能需求和复杂功能需求的项目。

React通过JSX与HTML结合,提升用户体验。1)JSX嵌入HTML,使开发更直观。2)虚拟DOM机制优化性能,减少DOM操作。3)组件化管理UI,提高可维护性。4)状态管理和事件处理增强交互性。

react有事件处理函数、useEffect和useCallback、高阶组件等等闭包。详细介绍:1、事件处理函数闭包:在React中,当我们在组件中定义一个事件处理函数时,该函数会形成一个闭包,可以访问组件作用域内的状态和属性。这样可以在事件处理函数中使用组件的状态和属性,实现交互逻辑;2、useEffect和useCallback中的闭包等等。
