React从入门到入土系列1-快速上手

这是我自己系统整理的React系列博客,主要参考2023年3开放的最新版本react官网内容,欢迎你阅读本系列内容,希望能有所收货。

阅读完本文后,你将收获:

  • 如何创建和嵌套使用react组件
  • 如何添加标记和样式
  • 如何展示数据
  • 如何渲染条件和列表
  • 如何响应事件和更新屏幕
  • 如何在不同组件之间共享数据

1 如何创建和嵌套使用react组件

React应用是由组件(components)组成的,组件是用户界面(UI)的一部分,它有自己的逻辑和外观。组件的范围很大,可以是一个完整的页面,也可以是一个小小的按钮组件。从react16之后,建议你使用函数式组件结合hook完成react应用开发*。

Note:如果你还不知道什么是函数式组件和hook,先忽略这两个概念,后续我们会作介绍。

举个简单的栗子,下面的几行代码就定义了一个最简单的react组件:

function MyButton() {
    
    
    return (
        <button>我是一个按钮</button>
    )
}

然后,你可以在其他react组件中使用这个MyButton组件:

export default function MyApp() {
    
    
  return (
    <div>
      <h1>欢迎学习React</h1>
      <MyButton />
    </div>
  );
}

像上面的栗子所示,MyApp是一个父组件,调用了MyButton组件,因此MyButton也就被称为子组件。运行上面的代码,你将看到:
在这里插入图片描述

特别说明:需要注意的是,在React中定义的组件名称是大写开头,且遵循大驼峰命名规则。

2 使用JSX编写标记(markup)

在前面的示例代码中出现的标记语法(markup syntax)被称为JSX(Javascript XML,javascript的扩展语言),主要特点是在js代码中编写标记语言。使用JSX编写React组件是可选的,但是大部分React项目都会使用JSX,因为用起来真的很香——很便捷(如果你用过optional API的话)。

相较于HTML,JSX更为严格。例如,你需要使用<br />而不是<br>,你的组件不能返回多个JSX标签——如果组件由多个并列的标签组成的话,需要在最外层使用<div> ... </div>或者<> ... </>包裹,如下面代码所示:

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

3 给你的组件添加样式

在React组建中,可以使用className给元素添加一个名字——就像在vuetemplate中给元素设置class一样,只不过换了个名字:

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

如果你希望给这个组件添加样式,可以创建一个AboutPage.css文件,然后在其中编写样式:

.title {
    
    
    font-size: 24px;
    color: green;
}

然后,在AboutPage.js中引用css样式:

import "./AboutPage.css";

function AboutPage() {
    
    
    ...
}

除了这种写法,你也可以定义一个AboutPage.module.css文件,其中内容和AboutPage.css一样:

.title {
    
    
    font-size: 24px;
    color: green;
}

然后在AboutPage.js中这样使用:

import styles from "./AboutPage.module.css";
function AboutPage() {
    
    
  return (
    <>
      <h1 className={
    
    styles.title}>About</h1>
      <p>Hello there.<br />How do you do?</p>
    </>
  );
}

这样做的好处是:由于使用了module css,因为css重名导致的样式污染问题被避免了,我更喜欢使用这种写法。

4 展示数据

JSX允许你在Javascript代码中编写标记语言,而且还支持使用花括号{}将数据再转义成Javascript,这样你就可以在JSX中嵌入一些变量:

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

使用花括号,你还可以将标记语言中的属性设置为变量,例如:className="avatar"将"avatar"字符串作为CSS类名,但src={user.imageUrl}user.imageUrl变量值作为img标签的src属性:

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

更进一步,你还可以将object类型的数据当做变量:

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

注意:在这个例子里面,style={ {}}并不是一种特殊的语法,最里层的{}只是一个对象外层的花括号而已。

5 条件渲染

在React中没有特别的语法用于编写条件判断(像vue中可以使用v-if, v-else),如果你需要编写条件渲染语句,只需要像在Javascript中那样使用if-else或者其他分支语句即可。如下面的例子:

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

当然,也可以使用三元表达式让代码看起来更优雅:

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

如果你不需要使用else分支,你也可以像下面这样写:

<div>
  {
    
    isLoggedIn && <AdminPanel />}
  {
    
    isLogined ? <AdminPanel /> : null}
</div>

这些条件分支的写法,对于JSX中的属性同样管用。

6 渲染列表

加入你有如下一个产品数据列表:

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

在React组件中,你可以使用map()函数将这个数组转换成<li>数组:

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

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

注意:使用map遍历生成的<li>组件有一个key属性,**对于列表中的每个项,应该给key属性传入一个字符串或数字,在其兄弟项中唯一地标识该项。**通常,key的取值应该来自你的数据,比如数据库ID。如果你的组件在后续有插入、删除或重新排序项操作,React借助key能够分清楚谁是谁,从而优化渲染性能。

7 响应事件

你可以通过在组件中声明事件处理函数来响应事件:

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

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

注意:onClick={handleClick}中的handleClick后面没有圆括号,你不需要在这里加上圆括号

8 更新屏幕

通常情况下,你希望你的组件能够记住组件中的一些数据并且将其展示出来。例如,你希望计算一个按钮被点击的次数,为了实现这个目的,你需要给组件添加一个state(状态),需要使用到第一个hook函数——useState

import {
    
     useState } from 'react';

然后你可以像下面这样声明一个变量count和对应的更新函数setCount,这些都是useState提供的,只需要像下面这样写:

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

然后,你就得到了两样东西:当前的状态(count)和该状态的更新函数setCount,你可以随意设置他们的名称,不过一般都是按照[something, setSomething]的风格进行命名。

MyButon组件第一次被渲染时,将显示count的默认值0。如果你希望更新count的值,就调用setCount()方法更新其取值:

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

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

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

上面的代码已经实现了一个五脏俱全的带有state的React组件。当你点击按钮时,count的取值将会+1。如果你多次渲染同一个组件,每个组件都会有自己独立的状态,如下面的代码:

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>
  );
}

运行结果:
在这里插入图片描述

9 使用Hooks

约定俗成,以use开头的函数被称为HooksuseState是一个React内置的钩子函数,在后续的学习中你会学到更多的钩子函数,也可以在API reference中查看。你也可以通过组合现有的hooks来编写自己的hook。

相较于其它函数,hooks的限制更大:你只能在组件(或者其他hook)的顶部调用hook,如果你想在条件或者循环中使用useState,需要提取一个新的组件并且将useState放在正确的位置,否则React会给出警告甚至错误。

10 在组件中共享数据

在前面的栗子中,MyButton组件独享其中的数据count,因此点击其中一个MyButton组件,并不会影响另外一个的取值:
在这里插入图片描述
那么问题来了,如果你希望让两个组件共享数据,应该怎么做呢?
如果希望两个兄弟MyButton组件共享数据,你需要将state上移到他们的公共父组件MyApp中:
在这里插入图片描述
现在,当你点击任意一个按钮,MyApp组件中的count就会更新,同时两个组件中的count值都会同时更新。那么,代码要怎么写呢?看下面的代码:

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

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

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

注意变动的内容:1、将countsetCountMyButton组件上移到了MyApp中;2、在MyButton组件中添加了countonClick(这些传递的数据或者响应函数被称为props),count是父组件传递给子组件的count的取值;onClick是事件处理函数,一旦点击了MyButton中的按钮,在父组件中就会执行一次handleClick函数。

MyButton组件将会变成下面这样:

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

上述代码运行结果如下图:
在这里插入图片描述

本文完,()。

猜你喜欢

转载自blog.csdn.net/qq_26822029/article/details/129718884
今日推荐