内容介绍
本专题假设你已经具备了基本的 HTML 5 、Javascript(ES6) 和 CSS 3 知识。本专题是为了补全 AXUM 全栈开发所需要的技术栈,而不是从零开始的前端课程,如果你还不具备以上知识,请通过其它途径学习完成之后,再来学习本专题。React: 简介与安装
本章将通过编程世界通用的“Hello World”程序,告诉你:创建 React 应用的几种方法、虚拟DOM、JSX以及将 React 挂载到真实 DOM 的步骤。- 支持试读
React:类式组件、函数式组件及state和props
本章将讨论 React 的类式组件、函数式组件以及 React 两个最重要的属性:`state` 和 `props`。 React: 组件的生命周期
本章将讨论 React 组件的常用生命周期。- 支持试读
React: 事件处理、表单处理及受控组件与非受控组件
本章讨论 React 的事件处理,以及表单处理时涉及两个策略:受控组件与非受控组件。 React: 流程控制与key
本章将讨论 React(JSX) 的条件判断和循环。React: 自定义组件及组件通讯
本章我们将正式开启 React 组件之路。虽然我们之前章节的都叫组件,但整个应用只有一个组件,略显单薄。同时,我们还将讨论组件之间如何进行通讯。React: 路由
本章将讨论 React 的路由:通过路由,你可以制作出“多页面”的系统。React: 状态共享
本章将通过一个非常典型的案例来讨论 React 的状态共享:只有登录用户才能看到某些内容。早期的 React 完全依靠其生态中的 redux 等第三方库来实现状态共享;现在 React 提供了官方的 `Context` 来实现这一目的。React: SEO挑战、服务端渲染及本地存储
经过紧张的学习,React 课程终于暂告一个段落了。本章将是一个相对轻松的内容,我们一起探讨一下 React 应用的 SEO 以及为什么需要服务端渲染,同时对 React 课程做个简单的小结。NextJS: 简介与安装
NextJS 是一个 React 框架,它提供了很多有用的功能把 React 的力量发挥地淋漓尽致。本章我们将开始 NextJS 之旅,首先自然是安装它,然后来一个「你好,NextJS」NextJS: 渲染模式和数据获取
趁你现在对我们刚刚讨论的有关 React 和 SEO 的问题还保持有较强的印象,我们先来讨论 NextJS 是如何利用多种渲染模式来应用 SEO 挑战的。NextJS: 内置组件及自动路由
NextJS 既然是 React 的框架,自然提供了一些内置组件来扩展 React。本章将介绍几个常用的 NextJS 内置组件,同时也将介绍 NextJS 的路由系统。NextJS: 开发博客系统
本章我们将使用 NextJS 开发一个小型的博客系统,你将学习到如何从远程服务器获取数据以及数据过滤、NextJS 常用组件的用法、NextJS 的自动路由等功能。Tailwind:简介与响应式设计的基本原则
TailwindCSS 是一款响应式的、移动设备优先的 CSS 工具类框架。本章对响应式布局、移动设备优先、断点等基本概念进行简要说明;并讨论几种安装 tailwind 的方式。Tailwind: 通过小示例体验它
本章通过两个小示例来体验一下 tailwind 的魔力。Tailwind: 默认配置
Tailwind 定义了一系列变量,比如颜色、大小、间距等。本章将介绍 tailwind 的一些默认设置。Tailwind: 撸一个按钮
本章将带你使用 tailwind 撸一个按钮Tailwind: 使用 flex 和 grid 进行响应式布局
本章我们将讨论使用 `flex` 和 `grid` 进行响应式布局,以及为什么不建议再使用 `float` 进行布局。- 支持试读
Tailwind: 撸一个带图标和动画效果的下拉框
本章将使用 tailwind 实现一个没有任何 Javscript 代码的纯 CSS 的下拉框,把应用到导航栏、菜单栏时,也被称为下拉菜单。同时我们将讨论如何在 tailwind 中使用图标,包括图标的进化史:从字体文件到SVG。 Tailwind: 撸一个报价卡片
本章我们将使用 tailwind 撸一个报价卡片。Tailwind: 撸一个响应式的纯CSS导航栏
本章将使用 tailwind 撸一个响应式的、纯 CSS 的导航栏。Tailwind: 集成到React/NextJS
本章将介绍如何将 Tailwind 集成到 React 或 NextJS 项目中。Tailwind: 复用
本章通过将之前撸的按钮改成 NextJS 版,进而讨论 Tailwind 的复用原则。Tailwind: 配置和插件
本章将讨论如何配置 tailwind,以及几个 tailwind 官方插件。Tailwind: 制作响应式博客
本章我们使用 tailwind 将之前课程中 NextJS 迷你博客改造为响应式的布局。
React: 流程控制与key
本章将讨论 React(JSX) 的条件判断和循环。
开始学习之前,请大声朗读三遍下面的内容:
如果你还无法区分表达式和语句,可以看看这个文档。
条件控制
Javascript 提供了很多用于条件控件的表达式(再次说明,这里要表达式,而不是 if/switch
这些语句),部分举例如下:
?:
:举例isCheck ? 'red' : 'blue'
??
:举例'foo'??'bar'
&&
:举例'foo' && 'bar'
||
:举例'foo' || 'bar'
- 以及其它
案例:
- 一个div和一个复选框
- 初始状态
- div 的背景颜色是蓝色
- 复选框未选中
- 复选框选中后,div的背景颜色变成红色
- 以上状态切换要做到轮换
- div 的背景颜色是蓝色
- 复选框未选中
import React from 'react';
function App() {
return (
<div>
<div
style={{
width: '10rem',
height: '10rem',
display: 'inline-block',
background: 'blue',
}}
></div>
<label>
<input type="checkbox" />
变变变
</label>
</div>
);
}
export default App;
import React, { useState } from 'react';
function App() {
const [isChecked, setChecked] = useState(false);
return (
<div>
<div
style={{
width: '10rem',
height: '10rem',
display: 'inline-block',
background: isChecked ? 'red' : 'blue',
}}
></div>
<label>
<input
type="checkbox"
checked={isChecked}
onChange={() => {
setChecked(!isChecked);
}}
/>
变变变
</label>
</div>
);
}
export default App;
- 第4行:创建名为
isChecked
的状态和对应的状态更新函数,用于保存复选框是否选中 - 第13行:使用
?:
运算符进行条件判断 - 第19行:将
isChecked
状态值设置为复选框checked
属性的值 - 第20~22行:使用匿名函数作为事件处理函数,进而改变选中状态
key
属性
在动态渲染的时候(比如遍历一个数组生成列表时),该属性必须指定,并且在当前组件内的值必须唯一。
很多人在遍历数组生成列表是,会想当然的用数组的索引作为 key 值,在某些场景这会导致灾难性的后果(比如动态添加、倒序排列列表)。
指定key的原则是:使用后端提供的、能唯一标识的值(比如数据库里的主键ID);除非你知道你在做什么,否则不要用数组索引做key。
key的指定很简单,比如:
<div key="foo"></div>
循环
既然无法使用语句,那在 JSX 中如何遍历数组呢?答案是使用 Javascript 的高阶函数:
map()
reduce()
filter()
- 以及其它
案例:
使用 React 显示 10 个用户的列表。
import React, { useEffect, useState } from 'react';
function App() {
const [users, setUsers] = useState([]);
useEffect(() => {
// 模拟从后端获取数据
setTimeout(() => {
setUsers([
{ id: 123, name: 'axum.rs-1', age: 18 },
{ id: 456, name: 'axum.rs-2', age: 14 },
{ id: 789, name: 'axum.rs-3', age: 21 },
{ id: 1011, name: 'axum.rs-4', age: 28 },
{ id: 1213, name: 'axum.rs-5', age: 38 },
{ id: 1415, name: 'axum.rs-6', age: 58 },
{ id: 1617, name: 'axum.rs-7', age: 82 },
{ id: 1819, name: 'axum.rs-8', age: 12 },
{ id: 2021, name: 'axum.rs-9', age: 13 },
{ id: 2223, name: 'axum.rs-10', age: 33 },
]);
}, 3000);
}, []);
return (
<div>
<h1>用户列表</h1>
<ul>
{users.map((user) => (
<li key={user.id}>
姓名:{user.name}, 年龄:{user.age}
</li>
))}
</ul>
</div>
);
}
export default App;
- 第4行:创建用于维护用户列表的状态及其设置函数
- 第6~22行:用于创建模拟数据。为了模拟从后端获取数据的等待过程,这里使用
setTimeout
设置了3秒后才回填数据 - 第28~32行:使用
map()
来遍历数组- 第29行:使用用户的
id
作为动态组件的key
- 第29行:使用用户的
- 第29行:使用用户的
id
作为动态组件的key
本节代码:axum-rs-jsx-loop-1
综合案例
下面对用户列表案例进行扩展:在从后端获取数据的时候,显示“正在载入”;获取数据完成之后才显示用户列表。
import React, { useEffect, useState } from 'react';
function App() {
const [users, setUsers] = useState([]);
const [isLoading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
// 模拟从后端获取数据
setTimeout(() => {
setUsers([
{ id: 123, name: 'axum.rs-1', age: 18 },
{ id: 456, name: 'axum.rs-2', age: 14 },
{ id: 789, name: 'axum.rs-3', age: 21 },
{ id: 1011, name: 'axum.rs-4', age: 28 },
{ id: 1213, name: 'axum.rs-5', age: 38 },
{ id: 1415, name: 'axum.rs-6', age: 58 },
{ id: 1617, name: 'axum.rs-7', age: 82 },
{ id: 1819, name: 'axum.rs-8', age: 12 },
{ id: 2021, name: 'axum.rs-9', age: 13 },
{ id: 2223, name: 'axum.rs-10', age: 33 },
]);
setLoading(false);
}, 3000);
}, []);
return (
<div>
<h1>用户列表</h1>
{isLoading ? (
<div>正在载入</div>
) : (
<ul>
{users.map((user) => (
<li key={user.id}>
姓名:{user.name}, 年龄:{user.age}
</li>
))}
</ul>
)}
</div>
);
}
export default App;
- 第5行:创建用于保存是否正在载入的状态
isLoding
及其设置函数 - 第8行:开始后端获取数据时,将
isLoding
设置为true
- 第23行:获取完数据,将
isLoding
设置为false
- 第30~40行:根据
isLoading
的值动态呈现不同的组件
本节代码:axum-rs-jsx-loop-2