ReactJS实战之JSX详解

举报
JavaEdge 发表于 2021/06/03 23:18:47 2021/06/03
【摘要】 创建虚拟DOM元素 什么是虚拟DOM 用js对象的形式,来表示DOM和DOM之间的嵌套关系。 const mydiv = React. createElement( 'div', { id: 'mydiv', title: 'div aaa' }, '这是一 个div元素' ) 12345 React. createElement 参数1 创建的元素的...

创建虚拟DOM元素

  • 什么是虚拟DOM
    用js对象的形式,来表示DOM和DOM之间的嵌套关系。
const mydiv = React. createElement(
	'div', 
	{ id: 'mydiv', title: 'div aaa' },
	'这是一 个div元素' 
)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

React. createElement

  • 参数1
    创建的元素的类型, 字符串,表示元素的名称
  • 参数2
    一个对象或 null,表示当前这个DOM元素的属性
  • 参数3
    子节点(包括其它虚拟DOM获取文本子节点)
  • 参数
    其它子节点
// 导包
import React from 'react'
import ReactDOM from 'react-dom'
// 创建虚拟 DOM 元素
const mydiv = React.createElement('div',{id:'mydiv', title: 'div aaa'}, '这是一个 div')
// 调用 render 函数渲染
ReactDOM.render(mydiv, document.getElementById('app'))

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

但如果元素很多,这样写就很不好呢,每次都要创建元素的 API。
毕竟页面上本质都是各种 html 标签,还是直接手写各种标签最简单暴力。

babel

但是HTML是标记语言。JS文件默认不能写这种HTML标记,打包会失败,使用 babel 来转换这些JS中的标签即可!

这种在JS中,混合写入类似于HTML的语法,叫做JSX。
符合 XML规范的JS。JSX 语法的本质,还是在运行的时候,被转换成了React. createElement形式执行。

引入JSX

  • 添加支持

  • 插件支持

  • 引入依赖

    React提供的环境搭建工具演示
    新建test项目

    yarn start
    可以将配置文件提出来
    yarn eject
    配置文件可读性差,因此不考虑使用这种现成方式写项目,跳过。

观察一下声明的这个变量:

const element = <h1>Hello, world!</h1>;

  
 
  • 1

这种看起来可能有些奇怪的标签语法既不是js 语法也不是 HTML语法,而是能在 js 中使用 html 标签,这被称为 JSX, 一种 JavaScript 的语法扩展。

推荐在 React 中使用 JSX 来描述用户界面。JSX 乍看起来可能比较像是模版语言,但事实上它完全是在 JavaScript 内部实现的。

JSX 用来声明 React 当中的元素。

JSX 的基本使用方法

在 JSX 中使用表达式

可任意地在 JSX 当中使用 JavaScript 表达式,在 JSX 当中的表达式要包含在大括号里

例如 2 + 2, user.firstName, 以及 formatName(user) 都是可以使用的

function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}

const user = {
  firstName: 'Harper',
  lastName: 'Perez'
};

const element = (
  <h1> Hello, {formatName(user)}!
  </h1>
);

ReactDOM.render(
  element,
  document.getElementById('root')
);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

书写 JSX 的时候一般都会带上换行和缩进,这样可以增强代码的可读性
同样推荐在 JSX 代码的外面扩上一个小括号,这样可以防止 分号自动插入 的 bug

JSX 本身其实也是一种表达式

在编译后,JSX 其实会被转化为普通的 JavaScript 对象

这意味着,你其实可以在 if 或者 for 语句里使用 JSX,将它赋值给变量,当作参数传入,作为返回值都可以

function getGreeting(user) {
  if (user) { return <h1>Hello, {formatName(user)}!</h1>;
  }
  return <h1>Hello, Stranger.</h1>;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

JSX 属性

“” 定义以字符串为值的属性

const element = <div tabIndex="0"></div>;

  
 
  • 1

{} 定义 js 表达式为值的属性

const element = <img src={user.avatarUrl}></img>;

  
 
  • 1

切记你使用了{}包裹的 js 表达式时就不要再到外面套引号了。

JSX 会将引号当中的内容识别为字符串而非表达式!

字符串数组

// 普通字符串数组渲染成js
const arr = ['1', '2', '3', '4'];

方式一:
// 定义一个空数组
const nameArr = [];
arr.forEach(item=> {
	const temp = <h5>{item}</h5>;
	nameArr.push(temp);
})

方式二:
{arr.map(item => <h3>{item}</h3>)}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

key 的处理

React 中需要把 key 添加给 forEach 或 map 或 for 循环直接控制的元素

arr.forEach(item=> {
	const temp = <h5 key={item}>{item}</h5>;
	nameArr.push(temp);
})

  
 
  • 1
  • 2
  • 3
  • 4
return ( <div> {arr.map(item => <div key={item}> <h3>{item}</h3></div> )} </div>
		);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

JSX 嵌套

若 JSX 标签是闭合式的,需在结尾处用/>, 就好像 XML/HTML 一样

JSX 标签同样可以相互嵌套

警告:
因为 JSX 的特性更接近 JavaScript 而不是 HTML , 所以 React DOM 使用 camelCase 小驼峰命名 来定义属性的名称,而不是使用 HTML 的属性名称
如 class 变成了 className
而 tabindex 则对应着 tabIndex

JSX 防注入攻击

可放心在 JSX 当中使用用户输入

React DOM 在渲染之前默认会 过滤 所有传入的值
它可以确保你的应用不会被注入攻击。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(跨站脚本) 攻击

JSX 代表 Objects

Babel 转译器会把 JSX 转换成一个名为 React.createElement()的方法调用

下面两种代码的作用是完全相同的

React.createElement()首先会进行一些避免bug的检查,之后会返回一个类似下面例子的对象

这样的对象被称为 “React 元素”。它代表所有你在屏幕上看到的东西。React 通过读取这些对象来构建 DOM 并保持数据内容一致。

JSX 的怪异之处

单一根节点

React 组件只能渲染一个根节点。为啥呢?先来看看render函数的一个返回示例:

return( <h1>Hello World</h1> 
) 

  
 
  • 1
  • 2
  • 3

它会被转换成一条语句:
return React.createElement("h1",null,"Hello World");
但面的代码却不是合法的:

return (  
<h1>Hello World</h1> 
<h2>Have a nice day</h2> 
) 

  
 
  • 1
  • 2
  • 3
  • 4

这并非JSX 的限制,而是JavaScript 的一个特性:一条返回语句只能返回单个值,而我们尝试返回两条语句(两次React.createElement 调用)。
解决的方法非常简单:就像你在普通JavaScript 中会做的那样,将所有返回值包含到一个根对象

return (  
<div> 
<h1>Hello World</h1> 
<h2>Have a nice day</h2> 
</div> 
) 

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

它完全有效,因为它会被转换成:

return React.createElement("div",null,  
React.createElement("h1",null,"Hello World"),  
React.createElement("h2",null," Have a nice day"),  
) 

  
 
  • 1
  • 2
  • 3
  • 4

它返回单个值,并且是通过合法的JavaScript 完成的。

  • 条件语句
    如果语句不兼容于JSX,看上去像是JSX 的限制所致,实际上却是因为JSX 只是普通的JavaScript
    回顾一下JSX 是如何被转换为普通JavaScript
    如下JSX
return ( <div className="salutation">Hello JSX</div> 
) 

  
 
  • 1
  • 2
  • 3

会被转换成这样的JavaScript

return ( React.createElement("div",{className:"salutation"},"Hello JSX");  
) 

  
 
  • 1
  • 2
  • 3

然而,如果尝试在JSX 的中间编写if 语句,例如:
<div className={if (condition) { "salutation" }}>Hello JSX</div>

它就会被转换成一个非法的JavaScript 表达式,如图2-1 所示:

image

  • 有什么解决方法?
    尽管并无可能在JSX 中使用“if”语句,但仍有根据条件渲染内容的方法,包括使用三元表达式和将条件赋值给一个变量(空值和未定义的值都会被React 进行处理,JSX在转义时什么都不会输出)。

使用三元表达式

如果你有一个非常简单的表达式,可以使用三元形式:

render() { return ( <div className={condition ? "salutation" : ""}> Hello JSX </div> )  
} 

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这段代码会被转换成一段合法的JavaScript:

React.createElement("div",{className: condition ?"salutation" : ""},  
"Hello JSX"); 

  
 
  • 1
  • 2

三元形式还可用来有条件地渲染整个节点:

<div> 
{condition ?  
<span>Hello JSX</span> 
: null}  
</div> 

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

将条件外置

如果三元表达式还不能应付你的要求,解决方法是不要在JSX 的中间使用条件。简单地将条件语句移动到外部(就像你在第2 章中隐藏和显示ContactItem 细节时所采取的方法)。

下面是原先的代码:

1.  render() {  
2.  return (  
3.  <div className={if (condition) { "salutation" }}> 
4.  Hello JSX  
5.  </div> 
6.  )  
7.  } 


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

将条件移动到JSX 的外部,就像:

render() {  
let className;  
if(condition){  
className = "salutation";  
}  
return (  
<div className={className}>Hello JSX</div> 
)  
} 

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

React 知道如何处理未定义的值,如果条件为假,它甚至不会在div 标签中创建class特性。

文章来源: javaedge.blog.csdn.net,作者:JavaEdge.,版权归原作者所有,如需转载,请联系作者。

原文链接:javaedge.blog.csdn.net/article/details/114323103

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。