06-15 2001人
JSX 基本概念
JSX
是JavaScript XML
的简写,表示了在 JavaScript 中书写 XML 格式的代码。它是React
的核心内容,它可以让我们在React
中创建元素更加简单,更加直观,提高开发效率。
- 什么是JSX?
JS
扩展语法,可以在JS
中书写XML
语法
- JSX的优点?
- 可以更加
简洁、直观、高效
的声明 UI 界面
- 可以更加
演示
我们可以在 babel 的网站,在线测试 babeljs ,这个网站可以把 JSX
代码转换成 JS
代码
注意:JSX
是 JavaScript
的语法扩展,它无法在浏览器中直接使用,在 create-react-app
脚手架中内置了 @babel/plugin-transform-react-jsx
插件来解析它,成为 JavaScript
的标准语法。
JSX 基本使用
- 导入
react-dom
- 使用
JSX
创建元素 - 使用
react-dom
渲染
import ReactDom from 'react-dom';
const element = (
<div id="box">
<h1>JSX</h1>
<ul>
<li>tom</li>
<li>jack</li>
<li>tony</li>
</ul>
</div>
);
ReactDom.render(element, document.getElementById('root'));
上述代码运行成功,现在 React17x
可以不必导入React
包,因为在 babel
转换的时候自动导入了创建 React 元素的依赖。但是如果你使用 React16x
那么你还需要手动导入 React
,如何验证?安装下低版本的 React
包即可。
总结
- 导入
react-dom
使用JSX
创建元素 使用react-dom
渲染元素 17x
版本的React
不需要导入,低版本
是需要导入的。
补充
vscode settings.json
加上 在 react 中使用 ement 语法提示创建标签
"emmet.includeLanguages": {
"javascript": "javascriptreact"
}
JSX 的注意事项
使用细节
- 特殊属性写法
className
htmlFor
- 没有内容的节点可以使用
单标签
- 必需有根节点,可以使用
<></>
幽灵标签,其实是<React.Fragment></React.Fragment>
简写 - 如果
JSX
有换行,最好使用()
包裹
代码示例
- 特殊属性
// class ---> className for ---> htmlFor 特殊属性
<div className="box">
<label htmlFor="ck"></label>
<input id="ck" type="checkbox" />
</div>
- 可单标签
// <span className="icon-edit"></span> 没内容可以写成单标签形势
<span className="icon-edit" />
- 有根节点
// 1. 使用 React.Fragment 代码片段
import React from 'react';
import ReactDom from 'react-dom';
const element = (
<React.Fragment>
<div>header</div>
<div>footer</div>
</React.Fragment>
);
ReactDom.render(element, document.getElementById('root'));
// 2. 使用<></>可以避免没必要的标签产生 简写 React.Fragment
import ReactDom from 'react-dom';
const element = (
<>
<div>header</div>
<div>footer</div>
</>
);
ReactDom.render(element, document.getElementById('root'));
- 用小括号
// 有换行的时候最好使用()可以让标签对其,避免没必要的错误
const element = (
<>
<div>header</div>
<div>footer</div>
</>
);
JSX 嵌入表达式
在JSX
中使用{ }嵌入JS
表达式,注意不能使用语句。
- 展示数据
- 进行运算
- 三元运算
- 使用函数
- 使用 JSX
- 使用注释
import React from 'react';
import ReactDom from 'react-dom';
// 数据
const data = {
name: 'tom',
age: 18,
};
// 函数
const up = () => {
return data.name.toUpperCase();
};
// jsx表达式
const list = (
<ul>
<li>jack</li>
<li>tony</li>
</ul>
);
const element = (
<div>
{/* 1. 使用数据 注释推荐快键键(ctrl+/) */}
<div>姓名:{data.name}</div>
<div>年龄:{data.age}</div>
{/* 2. 使用运算 */}
<div>明年几岁:{data.age + 1}</div>
{/* 3. 使用三元 */}
<div>是否成年:{data.age > 16 ? '是' : '否'}</div>
{/* 4. 使用函数 */}
<div>姓名大写:{up()}</div>
{/* 5. 使用JSX(jsx也是表达式) */}
<div>朋友:{list}</div>
</div>
);
ReactDom.render(element, document.getElementById('root'));
JSX 条件渲染
- 使用分支语句
if/else
完成条件渲染 - 使用
三元运算符
完成条件渲染 - 使用
逻辑运算符
完成条件渲染
if/else 条件渲染
const loading = true;
// 不能在JSX中写语句,但,可以充分利用JS能力
const getContent = () => {
if (loading) {
return <div>正在加载...</div>;
} else {
return <div>数据加载完毕,这是显示数据</div>;
}
};
const element = <div>{getContent()}</div>;
三元运算符 完成条件渲染
const loading = true;
const element = (
<div>
{loading ? <div>正在加载...</div> : <div>数据加载完毕,这是显示数据</div>}
</div>
);
逻辑运算 完成条件渲染
const loading = true;
const element = (
<div>
{loading && <div>正在加载...</div>}
{loading || <div>数据加载完毕,这是显示数据</div>}
</div>
);
JSX 列表渲染
- 可以渲染
JSX
数组 - 使用
map
渲染列表 - 直接在
JSX
中使用map
渲染列表 key
属性使用
可以渲染 JSX 数组
// 1. const list = ['tom', 'jack', 'tony'] 把数组转换成如下JSX数组
const list = [<li>tom</li>, <li>jack</li>, <li>tony</li>];
// 2. 把JSX嵌入在UL标签中
const elemet = <ul>{list}</ul>;
使用 map 渲染列表
// 1. 数据
const list = ['tom', 'jack', 'tony'];
// 2. 转jsx数组
const list2 = list.map((item) => <li>{item}</li>);
// 3. 使用
const element = <ul>{list2}</ul>;
直接在 JSX 中使用 map 渲染列表
// 1. 数据
const list = ['tom', 'jack', 'tony'];
// 2. 使用 map调用其实也是js表达式
const element = (
<ul>
{list.map((item) => (
<li>{item}</li>
))}
</ul>
);
key 属性使用
// Warning: Each child in a list should have a unique "key" prop.
// 1. 数据
const list = ['tom', 'jack', 'tony'];
// 2. 使用
const element = (
<ul>
{list.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
);
JSX 样式 - style 方式
style
接受一个采用小驼峰命名属性的JavaScript
对象,而不是CSS
字符串style
中的key
采用小驼峰命名是为了与JS
访问DOM
节点的属性保持一致React
会自动添加 ”px” 后缀到内联样式为数字的属性后,其他单位需要手动添加
演示代码
- 需求:去掉上一个列表案例
ul
的点,加上背景样式,设置字体大小,给第一个p
设置两倍字体大小
import ReactDom from 'react-dom'
// 1. 数据
const list = [
{ id: 100, name: 'tom', age: 15 },
{ id: 101, name: 'jack', age: 18 },
{ id: 102, name: 'tony', age: 20 }
]
+// 2. 样式
+const styleObject = {
+ listStyle: 'none',
+ backgroundColor: 'pink',
+ fontSize: 20
+}
// 3. 使用
const element = (
+ <ul style={styleObject} >
{list.map(item => {
return (
<li key={item.id}>
+ <p style={{fontSize: '2em'}}>姓名:{item.name}</p>
<p>是否成年:{item.age > 16 ? '是' : '否'}</p>
</li>
)
})}
</ul>
)
ReactDom.render(element, document.getElementById('root'))
JSX 样式 - className 方式
在多数情况下,应使用
className
属性来引用外部CSS
样式表中定义的class
className
设置类名,和class
属性要求一样只能是字符串- 如果需要根据数据设置类名,可以使用
{ }
嵌入JS
表达式实现
演示代码:
- 需求:在元素
button
上根据isActive
数据的值添加active
类名
index.css 代码
.button {
width: 100px;
height: 40px;
border: 1px solid #eee;
color: #999;
border-radius: 4px;
display: inline-block;
text-align: center;
line-height: 40px;
box-shadow: 2px 2px 10px #ccc;
cursor: pointer;
user-select: none;
}
.button.active {
background: #069;
color: #fff;
border-color: #069;
}
.button.block {
display: block;
width: 100%;
}
index.js 代码
import ReactDom from 'react-dom';
// 在src下新建index.css文件,导入进来即可
import './index.css';
const isActive = false;
const element = (
<span className={`button ${isActive ? 'active' : ''}`}>按钮</span>
);
ReactDom.render(element, document.getElementById('root'));
JSX 样式 - 动态 className
- 在使用
className
的时候遇见多个类名动态绑定,可以模仿vue
使用对象的方式 vue
中绑定类名的时候使用{类名:布尔}
用布尔值决定是否加上这个类名
例如:在元素 button
上根据 isActive
数据的值添加 active
类名,isBlock
数据的值添加 block
类名
import ReactDom from 'react-dom';
import './index.css';
// 数据
const isActive = false;
const isBlock = false;
// 类名对象
const classObject = {
button: true,
active: isActive,
block: isBlock,
};
// 转换成字符串
const className = Object.keys(classObject)
.filter((key) => classObject[key])
.join(' ');
const element = <span className={className}>按钮</span>;
ReactDom.render(element, document.getElementById('root'));
JSX 样式 - classnames 库
使用 JS
原生的能力处理多个类名的动态绑定,当然这样的需求已经有 classnames
库给我们解决了。
安装导入 classnames
# 安装
npm i classnames
# 或者
yarn add classnames
// 导入
import classNames from 'classnames'
认识 classnames API
// 1. 使用字符串
classNames('foo', 'bar'); // foo bar
// 2. 使用对象
classNames({ foo: true, bar: true }); // foo bar
// 3. 使用数组
classNames(['foo', 'bar']); // foo bar
// 4. 混合使用
classNames('foo', { bar: true }); // foo bar
例如还是上面那个需求:在元素 button
上根据 isActive
数据的值添加 active
类名,isBlock
数据的值添加 block
类名
import ReactDom from 'react-dom';
// 1. 导入classnames
import classNames from 'classnames';
import './index.css';
// 2. 数据
const isActive = true;
const isBlock = true;
// 3. 产生类名
const className = classNames('button', {
active: isActive,
block: isBlock,
});
const element = <span className={className}>按钮</span>;
ReactDom.render(element, document.getElementById('root'));
欢迎留言