3. React条件渲染
-
- 某些情况下,姐妹的内容会根据不同的情况显示不同的内容,或者决定是否渲染某部分内容:
- 在React中,所有的条件判断和普通的JavaScript代码一致;
-
- 常见的条件渲染的方式有哪些?
方式一: 条件判断语句
- 适合逻辑较多的情况
方式二: 三元运算符
- 适合逻辑比较简单
方式三: 与运算符&&
- 适合如果条件成立,渲染某一个组件;如果条件不成立,什么内容也不渲染
v-show的效果
- 主要是控制display属性是否为none
示例代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div id="root"></div> <script src="../lib/react.js"></script> <script src="../lib/react-dom.js"></script> <script src="../lib/babel.js"></script> <script type="text/babel"> // 1.定义App根组件 class App extends React.Component { constructor () { super() this.state = { message: 'hello world', isReady: false, friend: undefined } } render () { const { isReady, friend } = this.state // 1.条件判断方式一: 使用if进行条件判断 let showElement = null if(isReady) { showElement = <h2>准备开始比赛吧</h2> } else { showElement = <h2>请提前做好准备!</h2> } return ( <div> { /* 1. 方式一: 根据条件给变量赋值不同的内容 */ } <div>{ showElement }</div> { /* 2. 方式二: 三元运算符 */ } <div>{ isReady ? <button>开始战斗!</button> : <h3> 赶紧准备 </h3> }</div> { /* 3. 方式三: && 逻辑与运算符 */ } { /* 场景: 当某一个值, 有可能为undefined时,使用&&进行条件判断 */ } {/* 转成Boolean值时不显示的 */} <div>{ friend && <div>{ friend.name + ' ' + friend.desc }</div> }</div> </div> ) } } // 2. 创建root并且渲染App组件 const root = ReactDOM.createRoot(document.querySelector('#root')) root.render(<App/>) </script> </body> </html>
4. React列表渲染
-
- 真实开发中会从服务器请求大量的数据,数据会以列表的形式存储:
- 比如歌曲、歌手、排行榜列表的数据;
- 比如商品、购物车、评论列表的数据;
- 比如好友消息、动态、联系人列表的数据;
-
- 在React中没有像Vue模板语法中的v-for指令,而是需要通过Javascript代码的方式组织数据,转成JSX;
- 很多从Vue转到React的非常不习惯,认为Vue的方式更贱简洁明了;
- 但是React中的JSX正式因为和Javascript无缝的衔接,让他可以更加的灵活;
- React是真正可以提高我们编写代码能力的一种方式;
-
- 如何展示列表
- 在React中,展示列表最多的方式就是使用数组的map方法
-
- 很多时候在展示一个数组中的数据之前,需要先对他进行一些处理;
- 比如过滤掉一些内容:filter函数
- 比如截取数组中的一部分内容: slice函数
- 示例代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .item { border: 1px solid orange; margin: 10px; padding: 0 20px; } </style> </head> <body> <div id="root"></div> <script src="../lib/react.js"></script> <script src="../lib/react-dom.js"></script> <script src="../lib/babel.js"></script> <script type="text/babel"> // 1.定义App根组件 class App extends React.Component { constructor () { super() this.state = { students: [ { id: 111, name: 'why', score: 199 }, { id: 112, name: 'kobe', score: 98 }, { id: 113, name: 'james', score: 199 }, { id: 114, name: 'curry', score: 188 } ] } } render () { const { students } = this.state // 分数大于100的学生进行展示 const filterStudents = students.filter( item => item.score > 100) // 分数大于100,只展示两个人信息 // slice(start, end): [start, end) const sliceStudents = students.slice(0,2) return ( <div> <h2>学生列表数据</h2> <div className="list"> { students.filter(item => item.score> 100).slice(0, 2).map(item => { return ( <div className="item"> <h2>学号:{item.id}</h2> <h3>姓名:{item.name}</h3> <h1>分数:{item.score}</h1> </div> ) }) } </div> </div> ) } } // 2. 创建root并且渲染App组件 const root = ReactDOM.createRoot(document.querySelector('#root')) root.render(<App/>) </script> </body> </html>
-
- 列表中的key
- 在前面的代码中只要展示列表都会有报一个警告:
- 警告:Warning: Each child in a list should have a unique “key” prop.
- 翻译:在一个列表中每个子元素都应该有唯一的"key"属性
- 作用:在某些情况下(例如:插入)提高diff算法的效率
- 警告如图:
- 添加key属性后警告不提示:
- 这个警告是告诉需要再列表展示的jsx中添加一个key
- key主要的作用是为了提高diff算法的效率
- 具体内容后续再进行写笔记
5. JSX的本质
-
- 实际上,jsx仅仅只是React.createElement(component, props, …children)函数的语法糖;
- 所有的jsx最终都会被转换成React.createElement的函数调用。
-
- createElement需要传递三个参数:
- 参数一:type
- 当前ReactElement的类型
- 如果是标签元素,那么就使用字符串表示
- 如果是组件元素,那么就直接使用组件的名称
- 参数二:config
- 所有jsx中的属性都在config中以对象的属性和值的形式存储
- 比如传入className作为元素的class;
- 参数三: children
- 存放在标签中的内容,以children数组的方式进行存储;
- 当然,如果是多个元素呢? React内部有对他们进行处理,处理的源码在下放
-
- babel官网查看
- 默认jsx是通过babel帮我进行语法转换的,所以之前写的jsx代码都需要依赖babel。
- 可以子啊babel的官网中快速查看转换的过程:https://babeljs.io/repl#?browsers=react
-
- 自己编写React.createElement代码:
- 没有通过jsx来书写,姐妹依然是可以正常的渲染;
- 另外,在这样的情况下,不需要babel相关的依赖
- 所以,type="text/babel"可以删掉
- 所以,可以删除掉了;
- React.createElement代码如下:
React.createElement( "div", null,
“div”,
{
className: “header”
},
“Header”
),
/#PURE/ React.createElement(
“div”,
{
className: “Content”
},
/#PURE/ React.createElement(“div”, null, “Banner”),
/#PURE/ React.createElement(
“ul”,
null,
/#PURE/ React.createElement(
“li”,
null,
“\u5217\u8868\u6570\u636E1”
),
/#PURE/ React.createElement(
“li”,
null,
“\u5217\u8868\u6570\u636E2”
),
/#PURE/ React.createElement(
“li”,
null,
“\u5217\u8868\u6570\u636E3”
),
/#PURE/ React.createElement(
“li”,
null,
“\u5217\u8868\u6570\u636E4”
),
/#PURE/ React.createElement(“li”, null, “\u5217\u8868\u6570\u636E5”)
)
),
/#PURE/ React.createElement(
“div”,
{
className: “footer”
},
“Footer”
)
);
6. 虚拟DOM创建的过程
-
- 通过React.createElement做种创建出来一个ReactElement对象;
return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
-
- 这个ReactElement对象是什么作用? React为什么要创建它
- 原因是React利用ReactElement对象组成了一个
Javascript的对象树
; - Javascript的对象树就是
虚拟DOM(Virtual DOM)
-
- 如何查看ReactElement对象
- 可以将之前的jsx返回结果进行打印;
- 注意下面代码中jsx的打印;
-
- 而ReactElement最终形成的树结构就是Virtual DOM;
-
- jsx -> 虚拟DOM -> 真实DOM
- 编写相应的jsx代码,jsx代码转换完之后会变成对应的React.createElement()这样的一个函数调用,当函数执行完之后,会形成ReactElement对象;
并且这个对象也会有嵌套,有自己的children, 它也会形成一个嵌套,形成嵌套的话它就形成就是一个虚拟DOM,而虚拟DOM的话再经过渲染最后就变成真实的DOM; jsx代码 -> ReactElement对象 -> 真实DOM
div -> React.createElement('div', null, {}) -> ReactElement对象 -> 虚拟DOM -> 真实DOM
jsx代码
:ReactElement对象
:真实DOM
:- 类比Vue:是template解析 -> render函数 -> h函数 -> vnode -> 虚拟dom -> 真实dom
- 类比Vue解析,Vue解析时没有React直观的,Vue结项相对来说麻烦一点,有各种指令
-
- 虚拟DOM的作用:
-
- 在更新数据时,没有必要重新把整个一段代码给重新渲染,只需要更新数据,然后重新渲染对应的数据即可
- 例如:当依赖一个数据message, 当message数据改变时,会重新调用render函数,一旦调用render函数就会形成一个新的结构, 重新执行时会在次调用createElement,就会形成一个新的虚拟DOM结构,然后还有一个旧的虚拟DOM结构,会在新旧虚拟DOM之间做一个diff算法,比较新旧虚拟DOM之间的不同,如果只是数据发生改变时,只需要更新数据就可以了。
- 总结:可以在更新的时候进行diff算法,然后决定更新那里(可以在js对象里面快速进行diff算法来决定哪些东西更新,那些东西不更新)
-
- 跨平台,可以做跨平台应用程序
-
- 虚拟DOM帮助我们从命令式编程转到了声明式编程的模式;
声明式编程
-
- 虚拟DOM帮助我们从命令式编程转到了声明式编程的模式;
-
- React官方的说法:Virtual DOM 是一种编程理念
- 在这个理念中,UI以一种理想化或者虚拟化的方式保存在内存中,并且它是一个相对简单的Javascript对象;
- 可以通过root.render()让虚拟DOM和真实ODM同步起来,这个过程叫做协调(Reconciliation)
- 协调:
div -> ReactElement对象 -> 虚拟DOM -> 真实DOM
-
- 这种编程方式赋予React声明式的API:
- 只需要告诉React希望让UI是什么状态;
- React来确保DOM和这些状态是匹配的;
- 不需要直接进行DOM操作,就可以从手动更改DOM、属性操作、事件处理中解放出来;
-