Reactjs 清风拂面-快速开始

346 阅读5分钟

「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」。

什么是React

React 是一个JS库(不是框架),主要的目的是构建用户交互界面

它将复杂的用户交互界面,打破成一个个内嵌并且可复用的组件,然后拼接起来。

React本身不处理路由,样式,数据获取。如果你需要上面功能,可以考虑Nextjs框架

其他框架包括:

  • Gatsby React+GraphQL
  • Razzle 类似Next.js,但是配置方面更自由。

React能做什么

上面说过,React的主要作用是构建用户交互界面,从单个按钮到整个app。

除此之外,还有 React Native 可以用来创建Android,iOS App或者 Windows和macOS软件

React团队提供了React开发者工具可以查看网页是否有React开发。如果是,工具栏对应的按钮会点亮。

React开发需要Javascript

React是个JS框架,如果你要使用它,需要掌握Javascript,提供2个网站现代JavaS criptMDN中文查漏补缺。

React版本Hello World

下面代码描述了如何用React开发Hello World,非常简单,就2行代码。

function Greeting({ name }) {
  return <h1>Hello, {name}</h1>;
}

export default function App() {
  return <Greeting name="world" />
}

你可以点击这里在线查看和编辑具体的源码

学习React

React构建用户界面通过组件。一个组件可以是简单的按钮,也可以是复杂的整个页面。

参考一下图片,这是很常见的用户头像列表模块 gallery

这个列表,可以拆成3 x 用户头像(Profile)+一个画廊(Gallery)组件(用于包裹3个头像组件和文字)。

用React实现就是如下,具体代码看这里

function Profile() {
  return (
    <img
      src="https://i.imgur.com/MK3eW3As.jpg"
      alt="Katherine Johnson"
      className="avatar"
    />
  );
}

export default function Gallery() {
  return (
    <section>
      <h1>Amazing scientists</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}

这种有点像HTML标记语法的叫做JSX。JSX代表着JS+XML。大部分和HTML语法相同,比如上面的img标签,略微有点区别,比如JSX用className而不是class.

上面的数据是静态的,3个头像一模一样,如果要改成下面这样,头像数据由参数传入,展示不同的内容,该如何做呢?

props

React里面父组件传给子组件的参数统称 Props,因此 Profile组件可以改成下面的

function Profile({ name, imageUrl }) {
  return (
    <img
      className="avatar"
      src={imageUrl}
      alt={name}
    />
  );
}

export default function Gallery() {
  return (
    <section>
      <h1>Amazing scientists</h1>
      <Profile
        name="Lin Lanying"
        imageUrl="https://i.imgur.com/1bX5QH6.jpg"
      />
      <Profile
        name="Gregorio Y. Zara"
        imageUrl="https://i.imgur.com/7vQD0fPs.jpg"
      />
      <Profile
        name="Hedy Lamarr"
        imageUrl="https://i.imgur.com/yXOvdOSs.jpg"
      />
    </section>
  );
}

其中src={imageUrl}里面的{}花括号用于执行JS代码。

上面实现了 Profile 组件动态取数,但是Gallery里面还是写死了3个。一般来说这种头像列表的数据都是通过接口返回的,数量不确定,为了适应动态列表,我们可以将代码改为如下,完整参考这里

export const people = [{
  id: 0,
  name: 'Creola Katherine Johnson',
  imageId: 'MK3eW3A'
}];

export default function Gallery() {
  return (
    <section>
      <h1>Amazing scientists</h1>
      {people.map(person => (
        <Profile
          key={person.id}
          name={person.name}
          imageId={person.imageId}
        />
      ))}
    </section>
  );
}

最终展示如下图 dynamiclist

添加交互

上面显示如何展示一个列表,但是缺少交互比如加入购入车,toggle操作,轮播图点击显示下一个张图。

在React里面,用state变量来记录组件的状态。 如果要使用state涉及useState函数。这种以useXXX为开头的函数称为Hook,其主要作用就是让函数变成React的组件。useState入参是state变量的初始值,返回state变量和一个设置state变量值的函数。

const [index, setIndex] = useState(0);
const [showMore, setShowMore] = useState(false);

比如上面调用了useState函数2次,分别返回了index和showMore两个state变量,分别对应setIndex和setShowMore更新函数。

useState(x)里面的x入参可以是基本类型,也可以是对象或者数组,下面看一个todolist的例子,完整版这里

todolist


export default function List() {
  const [name, setName] = useState("");
  const [artists, setArtists] = useState([]);

  return (
    <section>
      <h1>伟大的诗人</h1>
      <input value={name} onChange={(e) => setName(e.target.value)}/>
      <button
        onClick={() => {
          //添加到列表
          setArtists([...artists, { name: name }]);
          //清空
          setName("");
        }}
      >
        Add
      </button>
      <ul>
        {/* //遍历 */}
        {artists.map((artist) => (
          <li>{artist.name}</li>
        ))}
      </ul>
    </section>
  );
}
  1. 调用useState 2次分别定义了name和artists两个state变量。其中name用于存储input的值,artists是个数组,循环遍历用来展示取到的值
  2. 监听input的onChange事件,调用setName函数给name赋值。然后将name用setArtist函数添加到数组里面
  3. 在ul中,{}表示jsx里面执行js语法,遍历输出列表

其他例子,源码分别是表单部分轮播部分 form

carosel

管理state

state初始值可以是基本类型也可以是对象数组,除了state,我们还有个props。

因此如何更好的管理state,其核心思想是避免重复定义state

需要遵守下面几条原则:

  1. 如果是常量,不要定义在state里面
  2. 如果是props里面的值,不要定义在state里面。
  3. 如果某个值可以通过其他属性计算出来,不要定义在state里面。
  4. 多个子组件存在排它操作,将state提升到父组件。

前面3条很好理解,主要是第四条排它操作。这种情况一般出现在一个列表需要高亮某一行的情况。为了高亮某一行,我们必须要有一个变量比如activeIndex记录具体哪行被高亮了,这时候,这个activeIndex定义在父组件里面比较合适。

属性计算例子,可以看这里修改前源码修改后源码

reductant

排它操作例子源码

nor