React基础
# React安装
React可以直接下载使用,也可以使用React CDN库,地址如下
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
// 将jsx语言转移为es5代码
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
2
3
4
通过npm或者yarn在已有项目中添加React支持
# 使用yarn:
$ yarn add react react-dom
# 使用npm:
$ npm install --save react react-dom
2
3
4
5
使用React开发新的项目
React 提供了一个官方的工具链,为应用快速搭建繁杂的脚手架,并且无需配置。
$ npm install -g create-react-app // 全局安装react官方工具链
$ npx create-react-app my-app // npx是 npm 5.2+版本的包管理运行工具
$ cd my-app $ npm start
2
3
# JSX简介
JSX全称为javascript XML,是一种 JavaScript的语法扩展,专门用来声明React 当中的元素。
react定义的一种类似于XML的JS扩展语法: JS + XML本质是React . createElement ( component , props , ... children ) 方法的语法糖
作用: 用来简化创建虚拟DOM
注意1:它不是字符串, 也不是HTML/XML标签
注意2:它最终产生的就是一个JS对象
面试题: json 与 xml 的区别
// json数据
{ "name": "demo01", "version": "0.1.0", "private": true }
2
<!-- xml数据 -->
<?xml version="1.0" encoding="UTF-8"?>
<o>
<name type="string">demo01</name>
<private type="boolean">true</private>
<version type="string">0.1.0</version>
</o>
2
3
4
5
6
7
我们来观察以下代码
const element = <h1>Hello, world!</h1>;
这里声明的常量element的值为xml标签语法,乍看起来可能比较像是模版语言,但事实上它完全是在 JavaScript 内部实现的。
JSX 其实就是一个Objects
Babel 转义器会把jsx 转化为一个名为React.createElement() 的方法调用。
// 注意在jsx语法中 元素的class属性必须改名为className,不能直接使用class
const el = [百度](http://www.baidu.com) // 这里是一个a标签,href="百度网址", 这里自动转成链接的形式了
//等价于
const el = React.createElement('a', {href: 'http://www.baidu.com',className: "hello"}, '百度')
2
3
4
然后 React.createElement()将会对内部参数进行检查并生成类似于下面的对象
// 注意: 以下示例是简化过的(不代表在 React 源码中是这样)
const element = {
$$typeof: Symbol(react.element), //区分对象是React元素描述对象还是其他对象
type: "h1",
props: {
href: "http://www.baidu.com",
children: "百度",
},
};
2
3
4
5
6
7
8
9
这样的对象被称为 “React 元素”。它代表所有你在屏幕上看到的东西。React 通过读取这些对象来构建 DOM 并保持数据内容一致
注意: 在react中对称性标签内部包含数据域都会作为当前React 元素props的children属性
基本语法规则
遇到 < 开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
遇到以 { 开头的代码,以JS语法解析: 标签中的js表达式必须用{ }包含
不能用引号包裹虚拟DOM
# JS表达式
- 在 JSX 属性和文本中可以使用大括号内部任意js表达式的形式,对元素的属性或文本内容进行差值。
例如“变量”、数学运算、字符串拼接、三元运算符、二元运算符 以及 函数的调用都js表达式并且jsx本身也是一种表达式。
let name = '小明'
let className = 'active'
let el = <div className={className + '-state'}>{name || '游客'}</div>
2
3
注意: 在className 属性差值中,React 不支持 Vue差值方法(传入数组 传入对象)。react只支持插入最终能渲染成字符串的js表达式。如果你想让React元素className像Vue一样绑定class请使用三方库。
- JSX语法与 XML/HTML 一样如果 JSX 标签是单一型,那么你必须要在结尾处用 /> 标签结束符。
const element = <img src={user.avatarUrl} >; // 错误! 单一型react元素没有结束符
const element = <img src={user.avatarUrl} />; // 正确
2
- JSX本质上就是js, React元素同样可以相互嵌套,但是每个React元素必须有且仅有一个根元素
let el1 = (<div></div> <div></div>) // 错误,因为本质上这段代码等价于下面代码,完全不符合js代码规范的
/*
let el1 =(
React.createElement('div')
React.createElement('div')
)
*/
let el1 = (
<div>
<div></div> <div></div>
</div>
) // 正确的当前React 元素有且仅有一个根元素
2
3
4
5
6
7
8
9
10
11
12
13
# JSX 防注入攻击
React DOM 在渲染之前默认会 过滤 所有传入的值。它可以确保你的应用不会被注入攻击。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(跨站脚本) 攻击。
// 你可以放心地在 JSX 当中使用用户输入:
let str = '<div>我是div吗></div>'
// 直接使用是安全的:
const element = <h1>{str}</h1>;
2
3
4
如果: 在开发中需要将字符串插入到Reacr元素中并且不经过上述防注入过滤,以HTML形式插入进去.使用dangerouslySetInnerHTML属性插值,注意请谨慎使用该属性并且一定不能把该属性暴露给用户。
let htmlObj = { __html: '<p>123</p>' }
<div dangerouslySetInnerHTML={ htmlObj } />
2
# 元素渲染
元素用来描述你在屏幕上看到的内容
const element = <h1>Hello, world</h1>;
与浏览器的 DOM 元素不同,React 当中的元素事实上是普通的对象,React DOM (虚拟DOM)可以确保 浏览器 DOM 的数据内容与 React 元素保持一致。
如何将元素渲染到 DOM 中?
- 首先我们在一个 HTML 页面中添加一个
id="app" 的 <div>
在此 div 中的所有内容都将由 React DOM 来管理,所以我们将其称之为 “根” DOM 节点。
<div id="app"></div>
我们用React 开发应用时一般只会定义一个根节点。
- 要将React元素渲染到根DOM节点中,我们通过把需要渲染的虚拟DOM都传递给 ReactDOM.render() 的方法来将其渲染到页面上
const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('app'));
2
# 元素更新渲染
React 元素都是immutable 不可变的。当元素被创建之后,你是无法改变其内容或属性的。一个元素就好像是动画里的一帧,它代表应用界面在某一时间点的样子。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- 将jsx语言转移为es5代码 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function render() {
let el = (
<div>
<h2>React时钟</h2>
<p>当前北京时间时:{new Date().toLocaleTimeString()}</p>
</div>
)
ReactDOM.render(el, document.getElementById('root'))
}
render()
// 因为没有学生命周期 这个示例通过 setInterval() 方法,每秒钟调用一次 ReactDOM.render().实现
setInterval(render, 1000)
</script>
<div id="app">
<h2>Vue时钟</h2>
<p>当前北京时间时:{{time}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
time: new Date().toLocaleTimeString()
},
mounted() {
setInterval(()=> {
this.time = new Date().toLocaleTimeString()
},1000)
}
})
</script>
</body>
</html>
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
打开控制台,我们比较Vue与React更新渲染发现即便我们每秒都创建了一个描述整个UI树的新元素,但是Vue更新整个p标签,而React只更新了p标签内发生改变部分插值文本。
更新渲染对比图
React DOM 也只会更新渲染文本节点中发生变化的内容。React DOM 首先会递归的比较元素内容先后的不同,而在渲染过程中只会更新改变了的部分。(diff算法)
也就是说React 只会更新必要的部分