JSX
什么是JSX?
下面的链接放的是React官网中关于JSX语法介绍的知识
但是我们都知道官方文档一般不说人话, 说通俗一点就是让你在JS中书写html, 同时可以跟vue一样可以在其中使用表达式, 甚至可以插入JS, 下面给大家总结了几点JSX语法的特点
- FaceBook起草的JS扩展语法
- 本质上是一个JS对象,会被babel编译(如果还不知道babel是什么的话可以百度babel然后进官方文档查看, 大致上来说就是一个语法降级工具)
- 每个JSX表达式, 有且仅有一个根节点
因为JSX表达式最终会被编译成React.createElement, 例如
const h1 = (
<h1>helloWorld<span>span元素</span></h1>
)
//上面这块会被编译成下面的内容
React.createElement('h1', {}, 'helloWorld', React.createElement('span', {}, 'span元素'));
//如果有两个根节点的话, babel将会不知道怎么编译, 没法用React.createElement来表示
const h1 = (
<h1>helloWorld</h1>
<span>span元素</span>
)
如果我们希望映射到真实的dom结构中是有两个根节点的话, 那么我们可能需要用到React.Fragment
const h1 = (
<React.Fragment>
<h1>helloWorld</h1>
<span>span元素</span>
</React.Fragment>
)
// 最后React.Fragment不会被映射进dom结构/ 类似于Vue的template
上面的React.Fragment其实还有一个语法糖, 写法如下
const h1 = (
<>
<h1>helloWorld</h1>
<span>span元素</span>
</>
)
// 实现的效果会跟React.Fragment一样
- 每个JSX元素必须被闭合(遵循XML规范)
在JSX中嵌入表达式
- 将表达式作为内容的一部分
const a = 10,
b = 20;
const h1 = (
<h1>{ a } * { b } = { a * b } </h1>
)
ReactDOM.render(h1, document.getElementById('root'));
// 那么页面会很标准的给我们渲染一个h1标签, 同时它的内容是 10 * 20 = 200
// 实际上上方的大括号被babel识别后, babel会给我们编译成如下
React.createElement('h1', null, `${a} * ${b} = ${a * b}`);
注意: null和undefined和false不会被显示
let a;
const h1 = (<h1>
{ null || a || false } (/*这里的a和null和false都是不会被显示的*/)
</h1>)
ReactDOM.render(h1, document.getElementById('root'));
不能放置普通对象, 我们常用来放置React元素对象
let infoArr = [
{name: 'fuhong'},
{name: 'fengzipeng'},
{name: '灰克特'}
]
// map方法如果还不了解的话可能需要回去看一些JS基础, key值的话以后会讲授原理
const lists = infoArr.map((item, index) => <li key={index}>姓名: { item.name }</li>)
ReactDOM.render(lists, document.getElementById('root'));
// 如上会给我们渲染一个li列表出来, 并且每个li中都是name 加上对应的item的name
- 将表达式作为元素属性
const src = 'https://dss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1321783629,1938099303&fm=26&gp=0.jpg'; // 我们定义了一张图片链接
const class = 'demo'; // 定义了一个类名
const div = (
<div>
<img src = {src} alt = '德国牧羊犬'>
(/*当我们书写了src = {src}的时候 上方定义的src就会被解析到img元素中*/)
<p className = {class}
style = {{width: '200px', height: '300px', backgroundColor: 'red'}></p>
</div>
)
- 属性使用小驼峰命名法
- 防止注入攻击
注入攻击的话大家如果不了解的话可以自行百度, React在防止XSS攻击也做得很好, 所以也给我们带来了不便, 如果我们真实的想将字符串作为innerHTML来解析的话, 我们需要如下操作
const content = '<h1>hello its me</h1>';
const div = (
(/*当设置了dangerouslySetInnerHTML并按照如下书写以后, content将不会以innerText解析*/)
<div dangerouslySetInnerHTML = {{ __html: content }}>
</div>
)
元素的不可变性
- 虽然JSX元素是一个对象, 但是该对象中的所有属性不可更改
let name = 'tom'
const h1 = (<h1>
hello, { name }
</h1>)
// 如果我们要访问h1这个React对象中的文本name属性, 在目前我们只能用h1.props.children来找到他
// 小伙伴们可以自行打印查看
h1.props.children[1] = 'tommy';
ReactDOM.render(h1, document.getElementById('root'));
当我们进行更改以后, 页面一定会报错, 如下
它告诉我们不能去给只读属性分配值, 所以JSX中的所有属性都是不可更改的
- 如果确实需要更改元素的属性, 那么我们需要重新创建JSX元素
let name = 'tom'
const h1 = (<h1>
hello, { name }
</h1>)
// 第一次渲染
ReactDOM.render(h1, document.getElementById('root'));
// 我们要修改name的值以后再重新渲染一次
name = 'adam';
ReactDOM.render(h1, document.getElementById('root'));
因为React的虚拟dom所以如上操作不会每一次都增删DOM对象, 大家也不用担心造成性能的消耗, 至于虚拟DOM, 下回见