03 React 基础:使用 React 和 Tailwind CSS 创建响应式公司网站

React简介

React 的历史与发展

React 是由 Facebook 的软件工程师 Jordan Walke创建的,并在2013年开源。它最初是为了解决 Facebook 巨大且复杂的 UI 问题而诞生的。

起初,React 专注于 "V"(View)部分,作为MVC 框架中的一部分。但是,随着功能的增加(如Flux 和后来的 Redux),React 逐渐成为了一种全面的前端应用库。

2019年发布的 React v16.8 引入了 Hooks,这改变了很多 React 开发的模式和习惯,使函数组件具有类似类组件的状态和生命周期特性,让函数组件更加强大。

至今,React 已经成为最流行的 JavaScript 库之一,国际上有大量公司使用 React 构建他们的网站和应用。

React 的优势与特色

  1. 声明式设计: React 采用声明式设计,让代码更容易理解以及预测结果。
  2. 组件化开发: 组件可以重复使用,提高开发效率和代码复用。
  3. Virtual DOM: React 创新地引入了 Virtual DOM 的概念,通过对比新旧 Virtual DOM 的差异来实现页面的有效更新,减少真实 DOM 的操作,进而提高性能。
  4. 单项数据流: 数据自顶向下流动,使得组件间的数据传递更清晰,方便追踪和调试。
  5. 生态系统: React 有一个庞大的社区和丰富的插件支持,如路由管理的 react-router,状态管理的 redux 或 mobx 等。同时它也有全面的测试工具例如 Jest 和 Enzyme,让我们更好地测试 React 应用。
  6. 跨平台开发: React Native 让我们可以使用 React 来开发原生移动应用。

环境配置和基础语法

如何配置React环境

由于我们的项目已经使用了 vite 模板,因此不需要再手动创建一个全新的 React 环境。如果我们需要在已有的 vite 项目添加 React 的支持,可以简单地通过两个步骤来做:

  1. 在项目中安装 React 和 ReactDOM:

    bash 复制代码
    npm install react react-dom
  2. 在 main.js 文件(或者 Index.js,这取决于你的项目的入口文件是怎样的)中,引入 React 和 ReactDOM,并渲染一个 React 组件:

    jsx 复制代码
    import { render } from 'react-dom';
    import React from 'react';
    
    function App() {
      return <h1>Hello, world!</h1>;
    }
    render(<App />, document.getElementById('root'));

然后,你就可以在 vite 项目中使用 React 了。

JSX 简介与使用

JavaScript XML(JSX) 是一种 JavaScript 的语法扩展。它看起来非常像 HTML,并且可以直接在你的 JavaScript 或是 TypeScript 文件中编写。在 React 中,JSX 起到了渲染 UI 的重要作用。

例如,下面的 JSX 代码定义了一个名为 'MyComponent' 的组件,该组件在页面上渲染 "Hello, World!":

jsx 复制代码
function MyComponent() {
    return <h1>Hello, World!</h1>;
}

要注意 JSX 只是语法糖,事实上他会被 Babel 这类工具编译成 JavaScript 方法调用。如 <div /> 最终将被转换为 React.createElement('div')。同时 JSX 区分大小写,如 <Div /> 将被编译为 React.createElement('Div'),代指我们自定义的 Div 组件而非 div 标签。

JSX 可以插入 JavaScript 表达式。只需在表达式周围包裹一对大括号 {},即可在 JSX 中使用任何有效的 JavaScript 表达式。例如:

jsx 复制代码
function MyComponent() {
    let name = 'John Doe';
    return <h1>Hello, {name}!</h1>;
}

由于我们使用了 Typescript,所以项目中将使用 TSX。

TSX 是 TypeScript 的一种扩展,它能够支持 JSX 语法。使用 TSX 处理 React 组件可以带来 TypeScript 静态类型检查的好处。

TSX 简介与使用

了解 TSX 之前,我们需要先知道什么是 TypeScript。TypeScript 是 JavaScript 的一个超集,增加了静态类型检查、类、接口等特性。使用 TypeScript 可以大幅提升代码的可读性和可维护性,也更适合大型项目开发。

JSX 是 JavaScript 的语法扩展,而 TSX 正是对 TypeScript 的语法扩展,允许我们将这种类 HTML 的语法直接用在 TypeScript 代码中。换句话说,TSX 就是在 JSX 的基础上加入了 TypeScript 的类型校验。

下面是一个简单的 TSX 实例:

tsx 复制代码
import React, { FC } from 'react'

interface Props {
  name: string;
  age: number;
}

export const Component: FC<Props> = ({ name, age }) => <div>{name}, you are {age} years old.</div>

上述代码定义了一个 React 函数组件,并且明确了该组件所接收的 props 的类型。其中,FCFunctionComponent 的缩写,在定义函数组件时常常被使用。当尝试向 Component 传递错误类型的 prop 时,TypeScript便会报错,此乃 TypeScript 强大的静态类型检查的优势。

注意,我们可以在文件名后缀为 .tsx 的文件中编写 TSX 代码,.tsx 是专门为 TypeScript 设计的 JSX 扩展。

什么是React组件

React应用都是由组件构成的。一个组件就是具有自己独立逻辑和外观的UI(用户界面)部分。组件可以小到一个按钮,大到一整个页面。在 React 中,组件通过 JSX 返回需要渲染的视图描述对象。这些描述对象被称为 "React Elements"。React 组件有两种主要的类型:函数组件和类组件。类组件属于过时的知识,我们暂且不予讨论。

函数组件因其简洁性及配合 Hooks 获得越来越广泛的使用。简单的函数组件示例:

jsx 复制代码
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

注意首字母是大写的。React组件名称必须始终以大写字母开头,而HTML标签一般为小写。

状态管理及事件处理

Props 和 State

在React中,props和state都是JavaScript对象,其中包含影响输出的信息。他们之间的主要区别在于props是不可变的(即你不能直接更改props),而state是专为数据存储设计的,这些数据可以在组件的生命周期内改变。

Props

当我们想通过子组件获取某个值时,父组件可以通过"属性"(props)将值传递给子组件。子组件读取到该属性值,但不能修改它。 例如:

jsx 复制代码
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// 使用 Welcome 组件:
ReactDOM.render(
  <Welcome name="Sara" />,
  document.getElementById('root')
);

在这个例子中,name就是一个prop。

State

State是组件自己管理的,可以任意修改,并会触发组件重新渲染。现在我们可以使用React的 useState hook在函数组件中定义state。

jsx 复制代码
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

在这个例子中,useState 定义了 count state变量以及更新它的setCount 函数。

如何进行事件处理

在按钮上添加一个点击事件类似于这样:

jsx 复制代码
function Button() {

// 定义事件处理器
const handleClick = () => {
    console.log('Button clicked!');
  };

  return (
// 设置事件监听器
		<button onClick={handleClick}>
      Click Me!
    </button>
  );
}

在上述示例中,我们在函数组件中直接使用了箭头函数来定义事件处理器,这免除了 this 绑定的问题。并且将其作为 onClick 属性的值,实现了点击事件的监听功能。

使用 Hook

React Hooks 是从 React 16.8 开始引入的新特性,它允许函数组件可以像类组件那样使用 state 和其他 React 特性(如生命周期函数等)。换句话说,通过 Hooks,我们就无需将一个函数组件转变为类组件就能够使用 state、生命周期方法和其他一些功能。

下面的这些 Hooks 都可以单独使用,也可以根据需要配合使用。而且如果我们有特定的逻辑需要复用,我们还可以自定义 Hooks。通过这种方式,Hooks 提供了一套更直观,更灵活的 API 来构建组件。

useState

useState 是最常用的 React Hook,让我们能在函数组件中添加 state(状态)。它接受初始值作为参数,返回一个数组,第一个元素是当前状态值,第二个元素是设置这个状态值的函数。

下面是一个使用 useState 的例子:

jsx 复制代码
import React, { useState } from 'react';

function Example() {
// 声明一个新的状态变量,我们将其称做 "count"const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useEffect

useEffect Hook 可以在函数组件中执行副作用操作。如请求数据,订阅,手动变更 DOM 等都可以看作是副作用。

jsx 复制代码
import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

上述代码表示:每次渲染后设置文档的标题。

自定义 Hooks

自定义 Hooks 允许你提取组件逻辑到可重用的函数。自定义 Hooks 是一种自然遵循 Hook 设计的约定,而非 React API 的一部分。命名规则是以 "use" 开头,并能调用其他的 Hook。

这是一个简单的自定义 Hook 示例,用于存储组件的本地状态:

jsx 复制代码
function useCounter(initialState) {
  const [count, setCount] = useState(initialState);
  function increment() {
    setCount(prevCount => prevCount + 1);
  }
  return [count, increment];
}

// 在组件中使用:function Component() {
    const [count, increment] = useCounter(0);

    return (
        <div>
            Count: {count}
            <button onClick={increment}>Increase Count</button>
        </div>
    );
}

其他常用Hooks

  • useContext: 接受一个 context 对象(React.createContext 的返回值)并返回当前 context 的值。它使得你可以订阅 React 的一个 Context 而无需使组件嵌套过深。
  • useReducer: 是一个替代 useState 的可选方案,适用于状态逻辑复杂且包含多个子值,或者下一个状态依赖于之前的状态的场景。
  • useCallback: 返回一个记忆版本的传入函数,只有当一项依赖项改变时它才会更新。
  • useMemo: 把"创建"函数和依赖项数组作为参数传入 useMemo,所以只要有一个依赖项改变,就会重新计算 memoized 值。
  • useRef: useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的对象将在组件的整个生命周期保持不变。

具体如何使用这些 Hooks,可以查看React文档来了解详细信息。

条件渲染和列表渲染

条件渲染

在 React 中,你可以使用条件语句(如 if 或三元运算符等)来根据特定条件决定是否渲染某一部分代码。这点与 JavaScript 是一样的。为了简便起见,我们经常用 JSX 和条件表达式(通常是三元运算符)一起使用。下面的例子通过 state 控制组件的显示与隐藏:

jsx 复制代码
import React, { useState } from 'react';

function Example() {
  const [isVisible, setIsVisible] = useState(true);

  return (
    <div>
      {isVisible ? <p>You can see me!</p> : null}

      <button onClick={() => setIsVisible(!isVisible)}>
        Toggle visibility
      </button>
    </div>
  );
}

列表渲染

列表数据的展示是很常见的需求。你可以利用 JavaScript 的 Array.prototype.map 方法和 JSX 来完成。在 React 中,一种常见的模式是通过数组的 map 方法,将数组中的每个元素转换成 JSX 的形式。请注意每个元素需要一个唯一的 "key" prop。

在下面的例子中,我们创建一个列表并为每个项目赋予一个唯一的键值:

jsx 复制代码
import React from 'react';

function NumberList({ numbers }) {
  const listItems = numbers.map((number) =>
    <li key={number.toString()}>
      {number}
    </li>
  );

  return (
    <ul>{listItems}</ul>
  );
}

// 使用 NumberList 组件const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

在上述例子中,<NumberList /> 接收一个 numbers props 并返回一个元素列表。记住,在列表中的每个项都应该有唯一的 key prop,通常在数组数据中可能存在一个适合做唯一标识的字段,否则可以使用元素索引(但要注意如果列表会进行排序、新增、删除操作时,索引可能会导致问题)。

相关推荐
我是天龙_绍37 分钟前
浏览器指纹,一个挺实用的知识点
前端
theshy38 分钟前
前端自制接口抓取工具:一键收集并导出接口列表
前端
wayne21441 分钟前
跨平台开发框架全景分析:Flutter、RN、KMM 与腾讯 Kuikly 谁更值得选择?
前端
LuckySusu41 分钟前
【js篇】JavaScript 对象创建的 6 种方式:从基础到高级
前端·javascript
LuckySusu43 分钟前
【js篇】async/await 的五大核心优势:让异步代码像同步一样清晰
前端·javascript
艾雅法拉拉43 分钟前
JS知识点回顾(1)
前端·javascript·面试
LuckySusu1 小时前
【js篇】Promise 解决了什么问题?—— 彻底告别“回调地狱”
前端·javascript
程序员海军1 小时前
如何让AI真正理解你的需求
前端·后端·aigc
passer9811 小时前
基于Vue的场景解决
前端·vue.js
用户458203153171 小时前
CSS过渡(Transition)详解:创建平滑状态变化
前端·css