# React——JSX 的使用
# 前言:代码管理史
早些年有很多开发者都认为 JavaScript
、HTML
、CSS
三者完全分离到不同的文件进行管理才是明智的方案。这样一来,项目中针对每个页面或者模块都会至少对应HTML
页面结构、CSS
页面样式展示、JavaScript
页面业务逻辑这三个文件。这样的编码风格虽然将页面组成的各个部分代码进行了隔离,方便了代码的管理,但是无形之中加重了代码的维护成本。同样,在这种假象的分离形式中,JavaScript 和 HTML 都是紧密耦合的,甚至说无论怎么放置 JavaScript 和 HTML ,他们之间的关系依然是紧密耦合的。因为在传统的开发形式中,JavaScript 免不了要去操作 HTML DOM 元素或向 DOM 元素中注入数据。另外,CSS 样式文件和 HTML 之间也存在类似一样的关系:CSS 中选择器遵循文档标记结构,几乎不可能在不影响某个 HTML 文件的前提下修改该文件,所以他们之前的关系也是紧密耦合的。
既然 JavaScript 文件,CSS 样式文件同 HTML 页面结构文件之间的关系都是紧密耦合的,那就为什么还要将他们拆分到不同的文件进行管理呢?那是因为在这之前没有一个很好的概念或者框架来处理这三种文件的关系。然而 React 提供了一种编写名为组件的小型代码块来组织应用的概念,并希望开发者将创建组件所用到的每项技术都封装在一起,并根据它们的领域和功能进行关注点分离,相应的出现了 CSS in JavaScript
的概念和 JSX
的语法。
初学 React
时,JSX
是我们遇到的第一个新概念。JSX
做为React
中模板语法的首选,而Vue
和Angular
则是首选使用template
模式,这里并不是要讨论哪一种方式更好,该篇文章会阐述 JSX 是什么以及在 React 中如何使用。下面,我们将着重讲解 JSX 相关的知识和用法。👇👇👇👇👇
# 一、初识 JSX
JSX(JavaScript Syntax Extension)
是 JavaScript 的语法扩展,是 Facebook 团队提出的一个语法方案,JSX 可以使得我们可以类似于 HTML 的形式去使用 JS。
在刚开始接触 React 的时候,大家肯定都会对它的元素描述语法感到好奇,就好似下面的语句:
const element = <h1>Hello, world!</h1>;
乍一看,这句标签语法并不是字符串,而是有点像 HTML 代码。但是根据我们已有的知识,HTML 代码是不能赋值给变量的,所以这肯定不是 HTML 代码了,这就是我们所说的 JSX。
JSX 算是 React 特有的标签语法了 (虽然 Vue 也借鉴了,但是写法不够简洁),用来声明 React 当中的元素 ,被称为 JSX。JSX 是一种 JavaScript 的语法扩展,推荐在 React 中使用该标签语法来描述用户界面。乍一看,JSX 语法可能比较像模版语言,但事实上它完全是在 JavaScript 内部实现的。
JSX 是 React 中声明式编程的体现方式 ,声明式编程,简单理解就是以结果为导向的编程。使用 JSX 将我们所期望的网页结构编写出来,然后 React 再根据 JSX 自动生成 JS 代码,所以我们所编写的 JSX 代码,最终都会转换成调用 React.createElement() 创建元素的代码。
const name = "JSX";
const element = <h1>Hello {name}</h1>;
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(element);
# 二、JSX 语法
JSX 有很强大的语法功能,在很好的实现功能的同时,也为我们描述 React 元素提供了极大的方便,以至我们可以像写 JavaScript 语法一样随心的描述 React 元素。既然这么神奇,那还不赶紧来试试 [兴奋地戳戳手]🤗。
# 👉 1. JSX 的使用规范
- JSX 不是字符串 不需要加引号
- JSX 中 html 标签应该小写。React 组件应该 大写
- JSX 的顶层只能有 一个根元素
- JSX 的标签必须正确结束(自然结束标签必须加“/”)
- 在 JSX 中可以使用{}在 {} 中嵌入 js 表达式
- 如果 JS 表达式为空值、布尔值、undefined 这些值,则不会显示
# 👉 2. 属性值类型
JSX 支持两种类型的属性赋值:使用引号来定义以==字符串为值==的属性和使用大括号来定义以 ==JavaScript 表达式为值==的属性。
// 以字符串为值的属性
const element = <div tabIndex="0"></div>;
// 当然你也可以写成,但是没必要
const element = <div tabIndex={"0"}></div>;
// 使用大括号来定义以 JavaScript 表达式为值的属性
const imgEle = <img src={user.avatarUrl} />;
# 👉 3. 支持 ES6 扩展语法扩展 props 属性
你可能经常会遇到这样的场景:你需要在 JSX 中传递一个已有的 props
对象,当然你不可能一个属性一个属性的全部将他们列出来,这是你可能会想到 ES6 属性展开(spread)操作符
,当然在 JSX 中这也是支持的,下面两种写法等价,第二种方式会更加灵活:
function App1() {
return <Greeting firstName="Ben" lastName="Hector" />;
}
function App2() {
const props = { firstName: "Ben", lastName: "Hector" };
return <Greeting {...props} />;
}
# 三、 JSX 的基本使用
# 👉 1. JSX 中使用 js 表达式
const name = '柴柴'
<h1>你好,我叫{name}</h1> // <h1>你好,我叫柴柴</h1>
可以使用的表达式
字符串、数值、布尔值、null、undefined、object( [] / {} )
1 + 2、'abc'.split('')、['a', 'b'].join('-')
fn()
🚨【注意】:if 语句/ switch-case 语句/ 变量声明语句,这些叫做语句,不是表达式,不能出现在
{}
中!!
# 👉 2. JSX 列表渲染
页面的构建离不开重复的列表结构,比如歌曲列表,商品列表等,我们知道 vue 中用的是 v-for,react 这边如何实现呢?
实现:使用数组的map
方法
// 来个列表
const songs = [
{ id: 1, name: "痴心绝对" },
{ id: 2, name: "像我这样的人" },
{ id: 3, name: "南山南" },
];
function App() {
return (
<div className="App">
<ul>
{songs.map((item) => (
<li>{item.name}</li>
))}
</ul>
</div>
);
}
export default App;
🚨【注意】:需要为遍历项添加
key
属性
key 在 HTML 结构中是看不到的,是 React 内部用来进行性能优化时使用
key 在当前列表中要唯一的字符串或者数值(String/Number)
如果列表中有像 id 这种的唯一值,就用 id 来作为 key 值
如果列表中没有像 id 这种的唯一值,就可以使用 index(下标)来作为 key 值
# 👉 3. JSX 条件渲染
作用:根据是否满足条件生成 HTML 结构,比如 Loading 效果
实现:可以使用 三元运算符
或 逻辑与(&&)运算符
// 来个布尔值
const flag = true;
function App() {
return (
<div className="App">
{/* 条件渲染字符串 */}
{flag ? "react真有趣" : "vue真有趣"}
{/* 条件渲染标签/组件 */}
{flag ? <span>this is span</span> : null}
</div>
);
}
export default App;
# 👉 4. JSX 样式处理
# 行内样式 - style
function App() {
return (
<div className="App">
<div style={{ color: "red" }}>this is a div</div>
</div>
);
}
export default App;
# 行内样式 - style - 更优写法
const styleObj = {
color: red,
};
function App() {
return (
<div className="App">
<div style={styleObj}>this is a div</div>
</div>
);
}
export default App;
# 类名 - className - 动态类名控制
import "./app.css";
const showTitle = true;
function App() {
return (
<div className="App">
<div className={showTitle ? "title" : ""}>this is a div</div>
</div>
);
}
export default App;
🚨【注意】:这里你应该注意的是 style 应该接受一个 Object 对象值,所以你应该包裹两层大括号(外面一层代表 JSX 模板语法,里面一层是对象语法),然后里面的属性值你应该写成 camelCase 小驼峰形式。
# 四、JSX 运行原理
JSX 是 React 特有的元素描述语法,用 JavaScript 的编码形式将 HTML、JavaScript 和 Style 很好的结合到了同一个文件,无疑是前端领域编码管理方面翻天覆地的变化。
JSX 作为 React.createElement() 语法糖的存在,实际上并不会被浏览器所认识,那肯定是在运行的背后做了代码转换,那这就涉及到 JSX 背后的原理了。
当我们在编辑器里面很舒服、很开心的写完 JSX 时,其实编译器在背后将我们写的 JSX 代码转译成了 React.createElement(component, props, ...children) 的形式。React.createElement 接受三个以上的参数:第一个是字符串或者变量,表示当前元素的类型,是 HTML 元素或者组件;第二个参数是当前元素的 props 属性的描述对象;第二个参数之后的所有参数都表示该元素的子代元素,当前元素有多少个直接子代,后面就有多少个参数。
🚨【注意】:JSX 并不是标准的 JS 语法,是 JS 的语法扩展,浏览器默认是不识别的,脚手架中内置的 @babel/plugin-transform-react-jsx 包,用来解析该语法