[REACT_DOC]-Quick Start

发布时间 2023-04-24 23:00:24作者: 暮冬有八

Quick Start

概览:

  • 如何创建以及嵌套组件
  • 如何添加markup 和样式
  • 如何展示数据
  • 如何条件渲染,如何渲染列表
  • 如何响应事件并更新渲染
  • 如何在组件之间共享数据

创建以及嵌套组件

function MyButton() {
  return (
    <button>I'm a button</button>
  );
}
export default function MyApp() {
  return (
    <div>
      <h1>Welcome to my app</h1>
      <MyButton />
    </div>
  );
}

注意: <MyButton />以大写字母开始, React 组件始终必须以大写字母开始, 而 HTML tags 必须是小写的。

export default 关键字声明了在这个文件中的 主组件

用 JSX 书写 标记(markup)

上面你所见到的 标记语法 被称作 JSX, JSX 相比较HTML而言,会更加的严格, 比必须关闭标签,例如 <br/> , 你的组件也不能够 return 多个 JSX tags, 你必须将返回的标签包裹, 例如 <div>...</div> 或者 <>...</>:

function AboutPage() {
  return (
    <>
      <h1>About</h1>
      <p>Hello there.<br />How do you do?</p>
    </>
  );
}

添加样式

在 React 中, 你需要通过 className 属性来执行一个标签的 class

<img className="avatar" />

接着, 你在一个独立的 CSS 文件中去书写CSS 样式:

/* In your CSS */
.avatar{
    border-radius:50%
}

React 并没有规定你如何去添加这个CSS 文件,在最简单的情况下,你可以直接添加一个 <link> tag 到你的 HTML 文件中,然后引入它。 如果你使用框架或者工具来构建 React项目, 那么你需要参看他们的对应文档以学习如何添加CSS 文件。

展示数据

JSX 允许你在一个花括号中插入一个变量以展示这个变量值。 例如:

return (
  <h1>
    {user.name}
  </h1>
);

同样的, 也可以为一个标签的属性指定变量值:

return (
  <img
    className="avatar"
    src={user.imageUrl}
  />
);

实际上, JSX 支持在花括号中解析更加复杂的表达式, 例如:

//App.js
const user = {
  name: 'Hedy Lamarr',
  imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',
  imageSize: 90,
};

export default function Profile() {
  return (
    <>
      <h1>{user.name}</h1>
      <img
        className="avatar"
        src={user.imageUrl}
        alt={'Photo of ' + user.name}
        style={{
          width: user.imageSize,
          height: user.imageSize
        }}
      />
    </>
  );
}

在上面的示例中, style={{}} 并不是一个特殊的语法, 而是style={} 语法花括号中的一个常规的 {} 对象。

条件渲染

在 React 中, 没有特定的语法去写 条件 渲染, 替而代之, 你可以直接使用 if 条件语句去完成:

let content;
if (isLoggedIn) {
  content = <AdminPanel />;
} else {
  content = <LoginForm />;
}
return (
  <div>
    {content}
  </div>
);

如果你更加喜欢简洁的代码, 那么你可以使用三元表达式:

<div>
  {isLoggedIn ? (
    <AdminPanel />
  ) : (
    <LoginForm />
  )}
</div>

甚至,如果你压根都不需要 else 分支,比可以使用一个简写的逻辑语法: &&

<div>
  {isLoggedIn && <AdminPanel />}
</div>

列表渲染

我们通常依赖 的特性,像for 循环, map 去渲染一个列表元素。 例如:

const products = [
  { title: 'Cabbage', id: 1 },
  { title: 'Garlic', id: 2 },
  { title: 'Apple', id: 3 },
];

在你的组件中, 使用map()函数去将一个数组转换为一个li 元素列表:

const listItems = products.map(product =>
  <li key={product.id}>
    {product.title}
  </li>
);

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

注意: <li> 有一个 key 属性 , 对于列表中的每一项, 你都应该传入一个字符串或者数字,用以标识该 项的唯一性 。这样,当随后发生了插入,删除,或者重排序,React 通过这个key 就能明白发生了什么。

const products = [
  { title: 'Cabbage', isFruit: false, id: 1 },
  { title: 'Garlic', isFruit: false, id: 2 },
  { title: 'Apple', isFruit: true, id: 3 },
];

export default function ShoppingList() {
  const listItems = products.map(product =>
    <li
      key={product.id}
      style={{
        color: product.isFruit ? 'magenta' : 'darkgreen'
      }}
    >
      {product.title}
    </li>
  );

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

事件响应

你可以通过在你的组件中定义一个 event handler 以响应发生对应的事件。

function MyButton() {
  function handleClick() {
    alert('You clicked me!');
  }

  return (
    <button onClick={handleClick}>
      Click me
    </button>
  );
}

注意: onClick={handleClick} 的末尾没有圆括号, 你只需要将这个事件的定义传入, React 将会在你随后点击这个按钮的时候再去调用这个事件。

更新屏幕

通常, 你会希望你的组件能够 “记住” 一些信息, 并展示它。 例如,或许你想要计数按钮被点击的次数。 要做到这点, 你需要添加 start 到你的组件。

首先,从 react 引入useState

import { useState } from "react";

现在你可以在你的组件内部声明一个 “状态” 变量:

function MyButton(){
    const [count,setCount]  = useState(0);
    //...
}

你将会从 useState 中得到两个东西, 当前的状态(count), 以及一个提供给你去更新它的 (setCount)。 你可以任意定义他们的名字,但是约定俗称的,我们喜欢写作 [something, setSomething].

按钮第一次展示的时候, count将会是 0 ,因为你给 useState() 传入了0, 这是它的初始值, 当你想要改变它的时候, 你需要调用 setCount() 方法, 并传入一个新的值。 :

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

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      Clicked {count} times
    </button>
  );
}

如果你多次渲染了相同的组件,每个组件都会维护一份自己独有的状态。

import { useState } from 'react';

export default function MyApp() {
  return (
    <div>
      <h1>Counters that update separately</h1>
      <MyButton />
      <MyButton />
    </div>
  );
}

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

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      Clicked {count} times
    </button>
  );
}

记住, 每一个按钮都会 "记住" 它自己的状态,并且不会影响其它的按钮。

使用 Hooks

使用 use 开头的函数,被称作 Hooks, useState 是一个 React 内置的 Hook, 你可在这里找到更多的 Hooks( API reference. ), 你也可以通过组合已有的hook从而创建你自己的 Hooks .

Hooks 相比较其他的函数而言, Hooks 更加具有限制性。 你只能在你的组件的顶部去调用 Hooks , 如果你想要在一个条件或者循环中使用 useState, 那么你应该抽离一个新的组件,并把Hooks 放在组件中。

在组件之间共享数据

在之前的示例中, 每个 MyButton 都有着自己独立的 count, 但是有的时候,你会希望多个组件共享同一份数据,一处发生变化,其他地方也随之变化。

还是以这个按钮的例子来说,如果你希望两个MyButton 组件共用同一个 count, 那么,你需要将 state 从独立的按钮组件中 提升 到同时包含这两个按钮组件的最近父级组件。

image

export default function MyApp() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>Counters that update together</h1>
      <MyButton count={count} onClick={handleClick} />
      <MyButton count={count} onClick={handleClick} />
    </div>
  );
}

function MyButton({ count, onClick }) {
  return (
   <button onClick={onClick}>
      Clicked {count} times
    </button>
  );
}

注意,在<MyButton count="..." onClick="..."> 上定义的这些属性,将会被包裹为一个对象作为参数传入给function MyButton({ count, onClick }){}, 这个对象被称作 props

当你点击任意一个按钮的时候, 被传入的onClick event handler 都将被触发, 也就是这个定义在 MyApp 中的handleClick 函数会被触发, 然后将count 加一。 接着,这个count 又会被传入到每个 按钮, 页面也会随之发生更新。