React 简介
React 由 FaceBook 开发,是一个开源的用于构建用户界面的 JavaScript 库。React 还有 React Native 框架,通过它可以直接使用 JS 开发原生应用。
React 的 特点如下:
- 虚拟 DOM (性能好,操作简单,兼容好)
- 声明式
- 基于组件
- 支持服务器端渲染
- 快速、简单、易学
React - Hello World
React 是用来代替 DOM 的,那么首先来看传统的 Dom 操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <body> <div id="root"></div> <script> const div = document.createElement('div'); div.innerText = "这是div" const root = document.getElementById('root'); root.appendChild(div) </script> </body>
|
如使用 React:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <head> <script src="script/react.development.js"></script> <script src="script/react-dom.development.js"></script> </head> <body> <div id="react-root"></div> <script> const reactDiv = React.createElement('div', {}, 'react hello world!') const rooter = ReactDOM.createRoot(document.getElementById("react-root")) rooter.render(reactDiv)
</script> </body>
|
这里用到了三个方法:React.createElement()
、ReactDOM.createRoot()
、root.render()
,接下来进行一下详细分析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| <body> <button id="btn">我是按钮</button> <div id="root"></div> <script> const button = React.createElement('button', { className: 'react-button', type: 'button', onClick: ()=>{ alert(1233) } }, "按钮");
const div = React.createElement('div', {}, '我是div', button) const root = ReactDOM.createRoot(document.getElementById('root')) root.render(div) const btn = document.getElementById('btn'); btn.addEventListener('click', ()=>{ const button = React.createElement('button', { className: 'react-button', type: 'button', onClick: ()=>{ alert('按钮变了') } }, "按钮2"); const div = React.createElement('div', {}, '我是div', button) root.render(div) })
</script> </body>
|
JSX (JavaScript Syntax Extension)
命令式编程:过程导向,告诉编译器,按照什么流程去执行命令:
如果使用上文提到的三个 API,只能以命令式编程的方式进行编程,例如:
1 2 3
|
const btn = React.createElement('button', {}, '按钮')
|
声明式编程:结果导向,告诉编译器,要什么结果,过程交给框架去实现:
1 2
| const div = <button>我是按钮</button>
|
在 React 中,可以通过 JSX ,以类似 HTML 的方式来创建 React 元素,JSX 需要使用 babel 编译为 JS 代码,才能被 React 执行
JSX注意事项
JSX 不是字符串,不加引号
JSX 中 html 标签小写,React 组件大写开头
JSX 中有且仅有一个根标签
JSX 标签必须要正确结束(自结束标签必须写斜杠)
JSX 中可以使用 {} 嵌入表达式(有值的就是表达式)
如果表达式是空值(布尔、空、undefined) 不会显示、
在 JSX 中,属性可以直接在标签中设置(class 需要使用 className 设置; style 必须使用对象设置)
渲染列表
在 jsx 中,{} 内只能放表达式,而不能放 if 语句
但可以在 if 语句中操作 jsx
1 2 3 4 5 6 7 8 9 10 11 12 13
| const name = 'Takuzen' const lang = 'en'
let div;
if (lang == 'en'){ div = <div> hello {name} </div> } else if (lang == 'cn'){ div = <div> 你好 {name} </div> }
const root = ReactDOM.createRoot(document.getElementById('root')) root.render(div)
|
如果要将 array 在网页中渲染,不需要使用循环,jsx会自动将数组进行遍历,然后渲染
1 2 3
| const array = ['孙悟空', '猪八戒', '沙和尚']
const list = <div> {array} </div>
|
如果要将 array 在网页中渲染为列表,可以将数组中的元素都包上 <li></li>
1 2 3 4 5 6 7 8 9 10 11 12 13
| const data = ['孙悟空', '猪八戒', '沙和尚'] const array = []
for (let i = 0; i < data.length; i++) { array.push(<li>{data[i]}</li>) }
const list = <ul> {array} </ul>
const root = ReactDOM.createRoot(document.getElementById('root')) root.render(list)
|
对数组遍历生成新数组的过程也可以使用 map() 方法实现:
1 2 3 4 5 6 7 8 9
| const data = ['孙悟空', '猪八戒', '沙和尚']
const list = <ul> {data.map(item => <li>{item}</li>)} </ul>
const root = ReactDOM.createRoot(document.getElementById('root')) root.render(list)
|
虚拟 DOM
在 React 中操作的是 React元素
,而非 原生DOM
元素
React 通过 虚拟DOM
将 React元素
和原生DOM
进行映射,虽然操作的是 React元素
,但这些操作最终会在 原生DOM
上 体现
虚拟DOM
有以下好处
降低 API 复杂度
解决兼容问题
提升性能(减少不必要的 DOM 操作)
每当调用 root.render()
时,页面重新渲染:
- React 会通过 diffing 算法,将新的元素和旧的元素进行比较(自上而下逐层对比新旧元素,如果上层就不一样,直接修改,一样再继续往下层比较)
- 通过比较,React 找到发生变化的元素,并且只对变化的元素进行修改,没有变化的不予处理
在 JSX 中显示数组,数组中每个元素都要设置一个唯一的 key,否则会显示警告,这是因为:
重新渲染页面时,React 会按照顺序依次比较元素,如果不指定 key,也按照顺序比较;
如果数组元素顺序没有变化,则没有影响,但如果列表顺序变化了,可能会导致性能问题(在最后添加没有影响,在开头添加可能导致全部重新渲染);
开发时一般使用 id 作为 key,有些场景可以使用 index 作为 key(性能较差,和没用index 一样,只能消除警告)