React 基础 - JSX
React 基础 - JSX
01. React 概述
目标:了解 React 是什么
官方文档(英文)、官方文档(中文)、官方文档(新版、开发中、英文)
官方释义:A JavaScript library for building user interfaces ( 一个用于构建用户界面的 JavaScript 库 )。
React 是一个开源的 JavaScript 库,用于构建 web 应用中的视图层,就是 web 应用中的前端用户界面。
React 是目前最为流行的前端框架之一。
https://npmtrends.com/angular-vs-react-vs-vue
https://trends.google.com/trends/explore?q=react,vue,angular
React 是由 Facebook 的软件工程师在 2012 年创建,于 2013 年 5 月开源,目前由 Facebook 以及个人开发人员和公司组成的社区维护。
React 起源于 Facebook 的内部项目,因为当时该公司对市场上所有 JavaScript 框架都不满意,就决定自己写一套用来架设 Instagram 的网站。
和其他前端框架相比 React 社区非常活跃,这就意味着在构建客户端 web 应用的过程中你遇到的问题几乎都可以在社区中找到答案。
https://stackoverflow.com/questions/tagged/reactjs
02. 创建 React 项目
目标:掌握使用脚手架创建 React 项目的方式
# 全局安装 react 官方提供的脚手架工具 create-react-app (CRA)
npm install create-react-app@5.0.1 -g
# 使用 CRA 创建项目, 项目名称为 react-basic
create-react-app react-basic
# 切换到项目根目录
cd react-basic
# 启动项目
npm start
# 创建项目的第二种方式
npm init react-app react-basic
# 项目结构分析
├── README.md # 项目的说明书
├── package.json # npm 包说明文件、记录项目信息
├── package-lock.json # 跟踪被安装的每个软件包的确切版本
├── public # 本地开发服务器提供的静态资源目录
│ ├── favicon.ico # 网站图标、显示在浏览器的标签栏中
│ ├── index.html # 项目的 HTML 模板
│ ├── logo192.png # react logo 图片 (示例代码中用于设置 IOS 移动端网站图标)
│ ├── logo512.png # react logo 图片
│ ├── manifest.json # web 应用清单如名称, 作者, 图标和描述 (主要用于将 Web 应用程序安装到设备的主屏幕)
│ └── robots.txt # 爬虫协议文件
└── src # 项目源码目录
├── App.css # 示例程序中的根组件样式文件
├── App.js # 示例程序中的根组件文件
├── App.test.js # 示例程序中的根组件测试文件
├── index.css # 示例程序中的全局样式文件
├── index.js # 项目的入口文件
├── logo.svg # 示例程序中根组件中显示的网站图标文件
├── reportWebVitals.js # 测试应用程序的性能
└── setupTests.js # 项目的测试文件
https://marketplace.visualstudio.com/items?itemName=dsznajder.es7-react-js-snippets
03. React 初体验
目标:创建 h1 标题元素、渲染该标题元素
<!-- 即将创建的 h1 元素 -->
<h1 title="Hello React" id="title">Hello React</div>
<!-- public/index.html -->
<!-- 将创建好的 h1 元素渲染到 id 为 root 的 div 中 -->
<div id="root">
<h1 title="Hello React" id="title">Hello React</div>
</div>
// src/index.js
// React 既可以构建在浏览器中运行的 web 应用, 也可以构建在移动端运行的原生应用, React 在构建这两种应用时会有一些通用方法和一些非通用方法, 通用方法都被放置在了 react 包中,非通用方法比如实现 web 应用的方法被放置在了 react-dom 包中, 实现移动端应用的方法被放置在了 react-native-web 文件中.
// react:核心库, 包含了构建 web 应用和构建移动端应用的通用方法.
import React from "react";
// react-dom:只包含了构建 web 应用的方法.
import ReactDOM from "react-dom/client";
// React.createElement(type, props, children): React 提供的创建元素的方式
// type: 标签名称, 字符串类型.
// props: 元素属性, 对象类型, 无属性填入 null
// children: 子元素, 普通文本或 createElement 方法返回的元素对象
// return: 元素对象
const title = React.createElement(
"h1",
{ id: "title", title: "Hello React" },
"Hello React"
);
// 创建 React 应用的根节点
const root = ReactDOM.createRoot(document.getElementById("root"));
// 将标题渲染到该根节点中
root.render(title);
练习:创建以下 HTML 结构并将其渲染出来。
<div class="list">
<h2>汽车</h2>
<ul>
<li>轿车</li>
<li>越野车</li>
</ul>
</div>
// 由于 class 在 JavaScript 是关键字, 所以在为元素声明类名时, 要使用 className
// createElement: 从第三个参数开始, 都是当前元素的子元素
const list = React.createElement(
"div",
{ className: "list" },
React.createElement("h2", null, "汽车"),
React.createElement(
"ul",
null,
React.createElement("li", null, "轿车"),
React.createElement("li", null, "越野车")
)
);
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(list);
04. JSX 概述
目标:了解 JSX 是什么、与 React.createElement 之间的关系
JSX 语法是另一种在 React 中创建元素的方式,使用它创建元素更加的简单、直接。
JSX 是 JavaScript XML 的简写,可以理解为在 JavaScript 中书写 XML 格式的代码 ( XML 跨平台 )。
JSXconst list = ( <div className="list"> <h2>汽车</h2> <ul> <li>轿车</li> <li>越野车</li> </ul> </div> );
问题一:既然 React.createElement 和 JSX 都可以创建元素,那么它们之间有什么关系吗?Babel REPL
虽然我们在编写代码时使用的是 JSX,但是在代码运行之前 babel 会将其转换为 React.createElement 方法的形式,所以它们之间是转换的关系。
问题二:为什么要将 JSX 转换为 React.createElement 方法?
JSX 是 Facebook 为是 JavaScript 添加的语法扩展,它并不是标准的 JavaScript 语法不能直接在浏览器中使用。

问题三:Facebook 为什么要创造 JSX 语法?
React 内部的性能优化机制要求在创建元素时必须使用 createElement 方法,而该方法对于开发者来说不友好,为了解决以上矛盾所以官方创造了 JSX 语法。
在有了 JSX 语法之后,开发者既能够以最熟悉的方式构建用户界面,React 又能使用 createElement 方法创建元素。
问题四:在使用了 JSX 之后为什么在 index.js 中没有用到 React 对象,还必须引入它呢?(React 17 版本之前)
因为 JSX 在执行前会被转换为 React.createElement 方法,如果不引入 React 对象程序在运行时找不到它就会报错。
在 React 17 及以后实际上我们也可以不导入 React 对象,在不导入 React 对象时 babel 将 jsx 转换为 jsxRuntime.jsx 方法且会自动导入 jsxRuntime。
jsxRuntime.jsx 方法和 createElement 方法一样,都是用于创建元素的。
补充:vscode 编辑器配置、在JavaScript 文件中启用 Emmet 插件的支持。
{
"emmet.triggerExpansionOnTab": true,
"emmet.includeLanguages": {
"javascript": "javascriptreact"
},
}
05. JSX 注意事项
目标:掌握 JSX 在使用时有哪些注意事项
(1) JSX 格式美化
如果 JSX 中存在多个标记建议使用小括号进行包裹,否则标签格式看起来稍显混乱。
JSX// 美化前 const jsx = <div> <ul></ul> </div>
JSXconst jsx = ( <div> <ul></ul> </div> );
(2) 在使用 JSX 语法创建元素时,元素的最外层必须要有一个根标记。
JSX// 错误写法 const jsx = ( <p>Hello</p> <p>world</p> )
JSX// 正确写法 const jsx = ( <div> <p>Hello</p> <p>world</p> </div> )
为避免因为要满足规定而出现无意义标记,React 提供了幽灵标记,幽灵标记在渲染后不会产生真实的 DOM 对象。
JSX// 幽灵标记的简写语法 const jsx = ( <> <p>Hello</p> <p>world</p> </> )
JSX// 幽灵标记的完整语法 const jsx = ( <React.Fragment> <p>Hello</p> <p>world</p> </React.Fragment> )
(3) 在 JSX 中使用单标记时单标记必须是闭合状态。
JSX<input type="text"/> <img src="" alt="" />
(4) 在JSX 中标记属性使用小驼峰式命名法。
小驼峰式命名法是指如果一个标识符由多个单词组成,第一个个单词的首字母小写、其他单词的首字母大写。
JSX<input maxLength="10" readOnly autoFocus />
(5) 在 JSX 中为元素添加属性时使用 className 替代 class、使用 htmlFor 替代 for
因为 JSX 本质上仍然是 JavaScript,而 class、for 是 JavaScript 中的关键字不能直接使用。
JSX<input type="text" className="todos" /> <label htmlFor="demo"></label>
06. JSX 嵌入表达式
目标:掌握什么是表达式、掌握如何在 JSX 中嵌入表达式
JSX 是React 中用来构建用户界面的手段,所以在 JSX 中嵌入表达式的目的是要将表达式产生的值渲染到用户界面中。
表达式就是一个能够产生结果的式子,就是说代码执行后一定会产生一个值作为结果。
10
"a"
3 + 4
10 > 100
const a = 10
"abc".split('')
['a', 'b', 'c'].join('_')
function fn () {}
在 JSX 中使用一对花括号 {} 嵌入表达式产生的值。
JSX// 插入文本内容 const name = "张三"; const jsx = <div>Hello, {name}</div>;
JSX// 插入属性值 const activeName = "active" const jsx = <input type="text" className={activeName} />
JSX// 执行计算 const x = 10 const y = 20 const paragraph = <p>{x * y}</p>
JSX// 渲染函数返回值 function getValue() { return "some value from getValue function" } const text = <p>{getValue()}</p>
JSX// JSX 表达式 const isError = true; const jsx = isError ? <div>发生了未知错误</div> : null;
JSX// 插入对象 const other = <p style={{width: 200}}>{{name: "李四"}}</p>
JSX// JSX 注释 const element = ( <> {/* 头部 */} <div>header</div> {/* 底部 */} <div>footer</div> </> )
非表达式不能被嵌入 JSX,以下为错误示范。
JSXconst jsx = <div>{if () {}}</div>
在 JSX 中,true、false、null,将不会被渲染为具有的内容。
07. JSX 条件渲染
目标:掌握在 JSX 中使用分支语句、三元运算、逻辑运算进行条件渲染 (根据条件决定渲染什么内容)
(1) 使用 if 分支语句进行条件渲染
JSX// 数据是否正在加载的标识 const isLoading = false; // 获取数据 function getContent() { if (isLoading) { return <span>数据加载中...</span>; } else { return <span>我是数据</span>; } } // 虽然在 JSX 中不能使用 if 语句 // 但是 React 中一切都是 JavaScript // 我们可以充分利用 JavaScript 的能力 const jsx = <div>{getContent()}</div>;
(2) 使用三元运算符进行条件渲染
JSX// 数据是否正在加载的标识 const isLoading = false; // 根据条件决定渲染什么内容 const jsx = isLoading ? <span>数据加载中...</span> : <span>我是数据</span>;
(3) 使用逻辑与运算符进行条件渲染
// 复习逻辑与运算符
// 在逻辑与表达式中只要有一个运算式返回假, 整个表达式返回假, 所有的运算式都返回真, 整个表达式返回真
true && false // false
true && true // true
false && false // false
false && true // false
// 逻辑运算符常见误区: 只要是逻辑表达式一定返回布尔值, 这是错误的
// 在逻辑与表达式中如果有运算式的返回结果转换为布尔值为假, 表达式的返回值就为该运算式的返回值
'' && 1 // ''
'a' && 0 // 0
// 在逻辑与表达式中如果所有运算式的返回结果转换为布尔值都为假, 表达式的返回值为第一个运算式的返回值
'' && 0 // ''
// 在逻辑与表达式中如果所有运算式的返回结果转换为布尔值都为真, 表达式的返回值为最后一个运算式的返回值
'a' && 1 // 1
JSX// 数据是否正在加载的标识 const isLoading = false; // 如果 isLoading 为 false, 短路 const jsx = isLoading && <span>数据加载中...</span>;
08. JSX 列表渲染
目标:掌握在 JSX 中渲染列表的方式
- JSX 中的数组自动展开特性
- 复习 JavaScript 数组 map 方法
- 在 JSX 中使用 map 方法进行列表渲染
① JSX 中的数组自动展开特性
在 JSX 中,可以将数组直接放入插值表达式,数组将会被自动展开,数组中的元素会被直接渲染到该位置。
const array = ["list-item-1", "list-item-2", "list-item-3"]
const jsx = <div>{array}</div>
const jsxArray = [
<li>list-item-1</li>,
<li>list-item-2</li>,
<li>list-item-3</li>,
];
const jsx = <ul>{jsxArray}</ul>;
注意:不能直接将对象数组嵌入到 JSX 中,因为当数组被自动展开后 JSX 不知道要如何渲染对象。
const arrayObject = [
{ name: "list-item-1" },
{ name: "list-item-2" },
{ name: "list-item-3" }
]
② 复习 JavaScript 数组 map 方法
map 方法用于对数组中的每一项数据依次进行转换,map 方法的返回值就是转换后的新数组。
let array = [1, 2, 3, 4]
let newArray = array.map((item, index) => item * index)
console.log(newArray) // [0, 2, 6, 12]
map 方法内部会对原始数组进行遍历,在遍历过程中不断调用传递到 map 方法中的回调函数,并将当前遍历的值和索引传递给回调函数,回调函数的返回值会被存储到一个新的数组中,遍历结束后返回新数组。
Array.prototype.map = function (callback) {
var result = [];
for (var i = 0; i < this.length; i++) {
result.push(callback(this[i], i));
}
return result;
};
③ 在 JSX 中使用 map 方法进行列表渲染
// 普通数据数组
const data = [
{ id: 1, name: "list-item-1" },
{ id: 2, name: "list-item-2" },
{ id: 3, name: "list-item-3" },
];
// 被转换后的 JSX 数组
// [<li>list-item-1</li>, <li>list-item-2</li>, <li>list-item-3</li>]
const jsxData = data.map((item) => <li key={item.id}>{item.name}</li>);
// 利用 jsx 中的数组自动展开特性渲染 JSX 数组
let jsx = <ul>{jsxData}</ul>;
// 在进行列表渲染时, 列表中的每一项必须要有 key 属性, 且属性值在当前循环中必须是唯一的, 它用于帮助 React 内部提升列表渲染性能
// 尽量不要使用循环索引作为 key 属性的值, 在一些特殊场景下并不能帮助 React 提升列表渲染性能, 比如动态拖拽列表元素更改列表项顺序时
// key 属性在 DOM 结构中是看不见的
09. JSX 元素样式
目标:掌握如何为元素添加行内样式、掌握如何为元素添加样式表样式
- 通过 style 属性为元素添加行内样式
- 通过 className 属性为元素添加样式表中的样式(全局样式)
- 通过 className 属性为元素添加样式表中的样式(组件级样式)
- 通过 classnames 第三方库为元素动态设置类名
(1) 通过 style 属性为元素添加行内样式
JSXconst styles = { width: 200, height: 200, backgroundColor: "skyblue", fontSize: 24, }; // style 属性接收对象作为参数, 对象属性为样式名称, 对象值为样式值. // 样式名称采用小驼峰命名法 // 如果样式值的单位是像素, 可以省略, 其他单位需要手动添加 const jsx = <div style={styles}></div>;
(2) 通过 className 属性为元素添加样式表中的样式(全局样式)
/* src/styles.css */
.box {
width: 100px;
height: 200px;
background: pink;
}
JSX// 导入样式表 import "./styles.css"; // 通过 className 属性为元素添加样式表中的样式 const jsx = <div className="box"></div>;
JSX// 如果个类名需要动态的被添加和删除可以在 JSX 中嵌入三元表达式 const isActive = true; const jsx = <div className={isActive ? "active" : ""}></div>;
(3) 通过 className 属性为元素添加样式表中的样式(组件级样式)
/* App.module.css */
.red {
color: red;
}
:global html {
height: 100%;
}
import styles from "./App.module.css";
export default class App extends React.Component {
render() {
return <div className={styles.red}>文字</div>
}
}
(4) 通过 classnames 第三方库为元素动态设置类名
思考:如果一个元素有多个类名需要根据不同的条件进行动态设置该怎么办呢?
通过 classnames 第三方库可以实现通过 className
属性为元素动态绑定任意个类名。
# 下载 classnames 第三方库
npm install classnames
// 注意: classNames 方法的参数个数没有限制, 且参数形式可以是字符串也可以是对象
classNames('foo', { bar: true }); // => 'foo bar'
JSX// 导入 classNames 方法, 用于动态为元素设置类名 import classNames from "classnames"; // 通过 classNames 方法为动态元素设置类名 const jsx = <div className={classNames("box", { active: true })}></div>;
10. 插入本地图片
目标:掌握在 React 应用中插入本地图片的方法
import logo from "./assets/images/logo.png";
export default class App extends React.Component {
render() {
return <img src={logo} alt="" />;
}
}
export default class App extends React.Component {
render() {
return <img src={require("./assets/images/logo.png")} alt="" />;
}
}
export default class App extends React.Component {
render() {
return (
<img src={`${process.env.PUBLIC_URL}/assets/images/logo.png`} alt="" />
);
}
}
11. JSX 元素事件
目标:掌握 JSX 中为元素添加事件的方式
1. 绑定事件
在 JSX 中,事件名称采用驼峰使命名法,事件处理函数通过插值表达式嵌入到 JSX 中。
语法: on+事件名称 = {事件处理程序}, 比如 onClick={onClickHandler}
JSXfunction onClickHandler() { console.log("clicked"); } // 此处需要特别注意: 在为事件添加事件处理函数时, 传入的一定是事件处理函数本身, 而不是加括号形式的函数调用 const jsx = <button onClick={onClickHandler}>button</button>;
JSX// 以下为错误写法 // 以下代码的含义是, 调用 sayHello 方法, 将 sayHello 方法的返回值赋值给 onClick 属性 const jsx = <button onClick={onClickHandler()}>Hello</button>;
JSX// 很多时候, 事件处理函数中只有少量代码, 我们也会将事件处理函数写在行内, 写成匿名的箭头函数 const jsx = <button onClick={() => console.log("clicked")}>Hello</button>;
2. 事件函数传参
在事件处理函数需要传递参数的情况下,我们可以先添加行内匿名箭头函数,当事件被触发后,先执行行内匿名箭头函数,再在行内匿名箭头函数中调用真正的事件处理函数,此时真正的事件处理函数就可以添加用于调用函数的小括号了,在小括号里就可以实现参数的传递了。
JSXfunction onClickHandler(arg1, arg2) { console.log(arg1); console.log(arg2); } const jsx = <button onClick={() => onClickHandler("a", "b")}>button</button>;
3. 事件对象
默认情况下,事件处理函数的第一个参数是事件对象。
JSXfunction onClickHandler(event) { console.log(event); } const jsx = <button onClick={onClickHandler}>button</button>;
在事件处理函数需要传递参数的情况下,开发者需要显式将事件对象传递到真实的事件处理函数中。
JSXfunction onClickHandler(arg1, arg2, event) { console.log(arg1); console.log(arg2); console.log(event); } const jsx = <button onClick={(event) => onClickHandler("a", "b", event)}>button</button>;
4. this 关键字
在 JSX 中,事件处理函数中的 this 并不指向触发事件的元素,而是指向 undefined。
因为在 React 不推荐我们直接操作 DOM 对象,而是要通过数据的改变驱动 DOM 的更新。
JSXfunction onClickHandler() { console.log(this); // undefined } const jsx = <button onClick={onClickHandler}>button</button>;
JSXfunction onClickHandler() { console.log(this); // undefined } const jsx = <button onClick={() => onClickHandler()}>button</button>;
JSX 综合案例-选项卡
目标:能够使用 JSX 完成腾讯首页选项卡数据的渲染工作 (切换暂时不做)
JSXconst jsx = ( <div className="container"> <div className="tab-title"> <h4 className="active">娱乐</h4> <h4>电视剧</h4> <h4>电影</h4> <h4>音乐</h4> </div> <div className="tab-content"> <ul className="active"> <li className="headline"> <img src="https://inews.gtimg.com/newsapp_ls/0/15171720914_640330/0" alt="" /> <div className="content"> <h3>马思纯开豪车逆向行驶,违反交规被通报罚款扣分记3分</h3> <span>我娱有约 12评</span> </div> </li> <li>从港剧歌手到《金宵大厦》演斯文败类,转型路上他最感恩马国明</li> <li>《新神榜:杨戬》定档8月19日,神话宇宙能否再度封神?</li> <li>北京交警通报网传“马某某交通违法”情况:驾车逆行被罚款计分</li> <li>曲折上升,吴磊的转型进行时</li> <li>这部草根纪录片,能治好我们的精神内耗吗</li> <li>胡一天说《民国大侦探》司徒颜不是徒有颜值,认证路垚更吃货</li> </ul> </div> </div> );
body,
h4,
ul {
margin: 0;
}
ul {
padding: 0;
list-style: none;
}
.container {
width: 500px;
margin: 70px auto 0;
}
.tab-title {
display: flex;
border-bottom: 1px solid #c9dff4;
height: 40px;
margin-bottom: 22px;
}
.tab-title h4 {
font-size: 20px;
color: #404040;
font-weight: normal;
margin-right: 35px;
cursor: pointer;
}
.tab-title .active {
color: #1479d7;
border-bottom: 4px solid #0276da;
}
.tab-content li {
font-size: 16px;
line-height: 36px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.tab-content .headline {
display: flex;
align-items: flex-start;
margin-bottom: 12px;
}
.tab-content .headline img {
width: 214px;
height: 120px;
}
.tab-content .headline .content {
margin-left: 16px;
display: flex;
flex-direction: column;
justify-content: space-between;
height: 120px;
}
.tab-content ul {
display: none;
}
.tab-content .active {
display: block;
}
.tab-content .headline h3 {
margin: 0;
font-size: 16px;
color: #333;
white-space: normal;
font-weight: normal;
line-height: normal;
}
.tab-content .headline span {
font-size: 13px;
color: #64788c;
line-height: normal;
}
const response = [
{
type: "娱乐",
list: [
{
title: "马思纯开豪车逆向行驶,违反交规被通报罚款扣分记3分",
imageUrl: "https://inews.gtimg.com/newsapp_ls/0/15171720914_640330/0",
comment: 10,
from: "我娱有约",
},
{ title: "从港剧歌手到《金宵大厦》演斯文败类,转型路上他最感恩马国明" },
{ title: "《新神榜:杨戬》定档8月19日,神话宇宙能否再度封神?" },
{ title: "北京交警通报网传“马某某交通违法”情况:驾车逆行被罚款计分" },
{ title: "曲折上升,吴磊的转型进行时" },
{ title: "这部草根纪录片,能治好我们的精神内耗吗" },
{ title: "胡一天说《民国大侦探》司徒颜不是徒有颜值,认证路垚更吃货" },
],
},
{
type: "电视剧",
list: [
{
title: "《玫瑰之战》袁泉颜值抗打,黄晓明不再油腻,为何输了口碑?",
imageUrl: "https://inews.gtimg.com/newsapp_ls/0/15168602214_294195/0",
comment: 5,
from: "文拉法辛",
},
{ title: "同剧中,当女配冒充女主,两人同款造型,就很考验女主颜值了" },
{ title: "仙侠剧:越拍越精美,越拍越架空,越拍越世俗" },
{ title: "4部古装剧,《琅琊榜》《甄嬛传》拿不到第1,第4部15年无法超越" },
{ title: "热度第一,全网刷屏,这剧烂不烂?" },
{ title: "《欢乐颂3》:为啥影视剧中穷人住的都是豪宅?" },
{ title: "《人世间》后又一大剧,芒果抽到“爆款”了,还诞生了“邪门CP”" },
],
},
{
type: "电影",
list: [
{
title: "王一博微博之夜红毯造型合集,荣获年度最受期待影片奖项",
imageUrl: "https://inews.gtimg.com/newsapp_ls/0/15168588151_294195/0",
comment: 20,
from: "胖编怪聊",
},
{ title: "10天仅收3.4亿!《明日战记》票房拉垮,古天乐拉票房让人心疼" },
{ title: "刘亦菲亮片点缀长裙优雅温柔 亮相微博电影之夜" },
{ title: "华谊王中磊:不会躺平,计划未来两年推出两部虚拟拍摄为主的电影" },
{ title: "秒售罄!尔冬升新作《海的尽头是草原》到底怎么样?" },
{ title: "1988年,好莱坞唯一一部在俄罗斯红场拍摄的电影《红场特警》上映" },
{ title: "微博电影之夜谁最火?王一博沈腾横扫热搜" },
],
},
{
type: "音乐",
list: [
{
title: "徐沛东:曾创作雍正王朝主题曲,一句失误惨遭下课,今近况如何",
imageUrl: "https://inews.gtimg.com/newsapp_ls/0/15168556970_294195/0",
comment: 50,
from: "无影剪哥",
},
{ title: "微博电影之夜:周深串烧歌曲展现真实唱功,单依纯稳定发挥获称赞" },
{ title: "好声音音源数据:李楚楚飙升榜排名第二,浙音学子潘韵淇未进前十" },
{ title: "中国首次曝光“垃圾”水乳!大牌上榜!国货真牛!" },
{ title: "黄霄雲使用按键留人,梁静茹率先出现组内PK,廖昌永收获学员" },
{ title: "“那个夏天”长沙交响乐团Melete室内乐团专场音乐会精彩上演" },
{ title: "陈奕迅主唱《孤勇者》背后的励志故事" },
],
},
];
JSXlet current = 0; const jsx = ( <div className="container"> <div className="tab-title"> {response.map((item, index) => ( <h4 className={index === current ? "active" : ""} key={index}> {item.type} </h4> ))} </div> <div className="tab-content"> {response.map((item, index) => { return ( <ul className={index === current ? "active" : ""} key={item.type}> {item.list.map((news, index) => { if (index === 0) { return ( <li key={index} className="headline"> <img src={news.imageUrl} alt="" /> <div className="content"> <h3>{news.title}</h3> <span> {news.from} {news.comment}评 </span> </div> </li> ); } else { return <li key={index}>{news.title}</li>; } })} </ul> ); })} </div> </div> );
React 是完全利用 JavaScript 语言自身的能力来增强 UI 的编写
Vue 是通过模板语法对 HTML 功能进行增强。