乐趣区

关于前端:React-入门

React 是一个用于构建用户界面的 JavaScript 库。它起源于 Facebook 的外部我的项目,因为该公司对市场上所有 JavaScript MVC 框架都不称心,就决定本人写一套,用来架设 Instagram 的网站。做进去当前,发现这套货色很好用,就在 2013 年 5 月开源了。

本文的大部分内容都能够在 React 的官网文档上找到,如果你想更加系统地学习 React,强烈建议你浏览一下官网文档。

Hello Word

一个最简略的 React 实例如下:

index.html

<div id="root"></div>

index.js

const element = <h1>Hello, world!</h1>;  # JSX

ReactDOM.render(
  element,
  document.getElementById('root')
);

下面的例子会在网页中打印出 Hello, world!
index.html 中定义了一个用作“根”DOM 节点的 <div> 元素,index.js 中应用 ReactDOM.render() 将一个 React 组件渲染到该“根”DOM 节点上。

index.js 文件的第一行有些特地,这种将 JS 与 html 混写在一起的语法是 JS 的一种扩大,被称为 JSX。因为这种将 html 元素和 JS 逻辑混写在一起形式可能很好地体现 React 的“组件化”设计思维,这里强烈推荐你在 React 中应用 JSX 语法,只管这不是必须的。

React 组件

在传统的前端开发形式中,html 与 JS 别离负责网页的内容出现(网页上须要显示哪些元素)和元素背地的行为逻辑,这种代码组织尽管层次结构十分清晰,但逻辑上却不够直观。React 将元素的出现代码(html)与其自身的逻辑代码(JS)先进行组合,从而形象出一个带有行为的逻辑的元素,即组件。这种代码组织形式更加合乎“所见即所得”的直观感触。此外,因为很多元素在大部分场景下对应的行为逻辑都是统一的,咱们 能够能够很容易地实现出标准化的 React 组件,在不同的场景下复用它们。

心愿上面的例子能够帮你对 React 的组件化有更具体的感触:

上面的两份代码均在页面上渲染了一个按钮,被点击后会在控制台记录按钮上显示的文本。

写法一. 应用 JS 和 html 将内容出现和元素逻辑离开
index.html

<!DOCTYPE html>
<html>
  <body>
    <div id="root">
      <button id="btn">Click me</button>
      <script src="index.js"></script> # 引入 js
    </div>
  </body>
</html>

index.js

let btn = document.getElementById("btn");
btn.addEventListener("click", function() {console.log(btn.innerText);
});

写法二. 应用 React 组件
react_index.html

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
</html>

react_index.js

function LogButton(props) {function LogText() {console.log(props.text);
  }
  return <button onClick={LogText}>{props.text}</button>;
}

ReactDOM.render(
  <LogButton text="Hello world!" />,
  document.getElementById('root')
);

写法二中的 react_index.js 中定义了一个函数组件 LogButton,该函数接管一个参数 props,蕴含了组件须要的所有属性,并返回一个 html 元素。在该例中,LogButton只有一个 .text 属性, 元素自带的逻辑 LogText即被点击后将按钮上的显示文本写入控制台日志。

除函数组件外,React 还反对类组件,能够参阅 React 的官网文档

Props 与 State

上一节提到,React 的组件接管一个参数 props,该参数蕴含了组件所须要的所有属性。须要特地留神的是,Props 是只读的,即 React 组件决不能批改本身的 Props。但在很多场景下,咱们须要动静的 UI,React 提供的 state 来反对这种需要。

上面的例子实现了一个计时器,在按下计时按钮后,显示曾经过的秒数:

import React, {useState, useEffect, useRef} from "react";

function SecondsCounter() {const [text, setText] = useState("start");
  const [timingState, setTimingState] = useState(false);
  const [time, setTime] = useState(0);
  const timer = useRef(0);

  useEffect(() => {if (timingState) {
      timer.current = setInterval(() => {setTime(t => t + 1)}, 1000
      );
    } else {clearInterval(timer.current);
    }
  }, [timingState]);

  function clickHandle() {if (timingState) {setTimingState(false);
      setText('start');
    } else {setTimingState(true);
      setText('pause')
    }
  }
  return (
    <div>
      <button onClick={clickHandle}>{text}</button>
      <p>{time} seconds had passed.</p>
    </div>
  );
}

ReactDOM.render(
  <SecondsCounter />,
  document.getElementById('root')
);

下面的例子会在页面上渲染出一个按钮和按秒为单位的计时后果,初始状态下,按钮上显示的内容为 start,点击按钮后,计时开始,按钮上显示的内容变为 pause,再次点击后,计时暂停,按钮上的本文变回 start。

这里从 React 库引入了 useState,useEffect,useRef 三个函数,这些以 use 结尾的函数被称为 HOOK,上面逐个介绍它们的用法:

useState

useState能够定义一个组件可能扭转的 state,根本应用形式为:

const [state, setState] = useState(0);

useState会返回一个数组,数组的第一个元素是一个 state 变量,第一个元素是用于设置该 state 变量的函数,它们的名称并不是 useStateAPI 的一部分,你能够取本人想要的名字。传入useState 的参数是该 state 变量的初始值,这里是 0,故该 state 是一个 number 类型的变量,当然你也能够定义其余类型的 state 变量,例如传递一个字符串给 useState 来获取一个字符串类型的 state,你甚至能够给 useState 对象来定义一个简单 state

const [complexState, setComplexState] = useState({name: "Tom", age: 18})

想要扭转 state 时,能够应用 useState 返回数组的第二个元素,但请留神,不要间接批改 state

const [state, setState] = useState(0);
setState(1); // 将 state 设置为 1
state = 2;// error!!!不能间接批改 state

state 可能是异步的
处于性能思考,react 并不会在 setState 调用后立即批改 state,而是将所有的 setState 进行合并后再执行,这可能导致一个令老手困惑的状况

const [state, setState] = useState(0);
setState(state + 1); // 此时 state 的值是 0
setState(state + 1); // 此时 state 的值仍是 0

在上述代码执行结束,渲染下一帧时,state 的值并不是 2 而是 1。但有时候咱们想要的可能不是这种成果,例如在下面的计时器例子中,咱们想要 time 每隔一秒就主动加 1,能够将一个函数传入 setState

const [time, setTime] = useState(0);
setTime(time => time + 1);

这里 time => time + 1 是一个简化的箭头函数,箭头函数是 ES6 规范新增的一种函数,箭头函数语法直观,定义匿名函数十分不便
例如,对于函数

function add(a, b) {return a + b;}

相应的箭头函数的写法

(a, b) => {return a + b;}

当箭头函数的返回体只有一条返回语句时,能够简写为

(a, b) => a + b;

更多无关箭头函数和 JS 的常识能够参阅 JavaScript 教程

退出移动版