【30-Days-Of-React】初识React

236 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情

最近打算学习一下react,之前一直都是在使用vue,一直都听说react挺火的,想了解一下和vue有什么不一样,刚好在github上看到了一个30-Days-Of-React的项目,因此想开一个专栏来记录一下学习react的过程

本专栏不会严格按照30 days去写30篇文章,大致看了一下其实发现很多东西都比较基础,所以一天内都能学挺多的了其实,不过今天是第一天,就还是简单记录一下,对react有个大概认知先,后续的文章我会将多天的内容整合到一篇文章来发布

由于只是简单使用,所以不会通过脚手架的方式去创建,而是用CDN的方式,方便我们快速上手

1. 认识JSX

首先介绍一下JSX,全名是JavaScript XML,它允许我们直接在js中编写html的代码 在vanilla(也就是原生js)中,我们都是通过createElement这一API创建DOM元素去动态操作html的 而在react中,并不需要显示调用类似createElement这样的API,而是通过JSX直接表示要用到的DOM元素 但是JSX并不是纯js代码,它是怎么被浏览器解析执行的呢?可以通过babel帮助我们完成这一需求,这个待会搭建环境的时候会讲到 首先大概了解一下JSX长啥样吧,既然说了是直接在js中编写html,那么很理应长成下面这样

const jsxElement = <p>Hello JSX</p>

可以看到,并不需要加上任何引号表明它是一个字符串,直接使用html的标签即可


2. 搭建环境

2.1 通过babel转换jsx代码

由于要使用babel帮我们将jsx代码转成js代码,所以我们的cdn中需要引入babel

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Getting Started React</title>
  </head>
  <body>
    <div id="app"></div>

    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <script type="text/babel">
      // 这个 script 标签中的代码会被 babel 处理
    </script>
  </body>
</html>

2.2 引入react和react-dom

reactreact-dom应当放在babel的上面,这样才能被babel处理

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Getting Started React</title>
  </head>
  <body>
    <div id="app"></div>

    <script
      crossorigin
      src="https://unpkg.com/react@16/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"
    ></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <script type="text/babel">
      // 这个 script 标签中的代码会被 babel 处理
    </script>
  </body>
</html>

body中有一个idappdiv标签,作为整个react项目的挂载容器,所以我们需要获取到这个DOM元素,这是整个项目中唯一一处要使用原生操作DOM的地方

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Getting Started React</title>
  </head>
  <body>
    <div id="app"></div>

    <script
      crossorigin
      src="https://unpkg.com/react@16/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"
    ></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <script type="text/babel">
      // 获取根元素作为 react 挂载的容器
      const app = document.querySelector('#app');

      // 创建一个 JSX 元素
      const jsxElement = <h1>Hello JSX</h1>;

      ReactDOM.render(jsxElement, app);
    </script>
  </body>
</html>

运行后就能够将jsx元素渲染出来了 image.png


3. 使用JSX

前面我们简单地创建了一个jsx元素,并通过ReactDOMrender函数将jsx挂载到了根容器元素中,接下来我们看一下jsx的更多用法

3.1 组合多个JSX

假设我们的网页会有headermainfooter三部分,如果全都写成一个jsx会不太好管理 所以我们可以单独写成三个jsx

// 获取根元素作为 react 挂载的容器
const app = document.querySelector('#app');

// 创建三个 jsx 元素
const header = (
  <header>
    <h1>Hello JSX</h1>
  </header>
);

const main = (
  <main>
    <p>
      Lorem ipsum dolor, sit amet consectetur adipisicing elit. Facilis
      animi, tempora tenetur eos commodi, veritatis atque qui obcaecati
      reiciendis fugit nemo repellat architecto, impedit dolor aliquam
      saepe illum ut nobis?
    </p>
  </main>
);

const footer = (
  <footer>
    <p>Copyright 2022</p>
  </footer>
);

// 将三个 jsx 元素组合起来
const appJsx = (
  <div>
    {header}
    {main}
    {footer}
  </div>
);

ReactDOM.render(appJsx, app);

就是通过{}将对jsx对象的引用变量放入即可,效果如下: image.png


3.2 内联样式

jsx中,可以直接使用内联样式,这和html中的使用是一样的,但是给style属性赋值的时候,是要传递一个对象的,这也就意味着我们需要像前面那样,使用{}将对象包裹起来,这样才能被jsx识别,对象可以是直接字面量写在jsx中,或者用变量引用一个对象传入也行

const main = (
  <main style={{ backgroundColor: 'skyblue', fontSize: '24px' }}>
    <p>
      Lorem ipsum dolor, sit amet consectetur adipisicing elit. Facilis
      animi, tempora tenetur eos commodi, veritatis atque qui obcaecati
      reiciendis fugit nemo repellat architecto, impedit dolor aliquam
      saepe illum ut nobis?
    </p>
  </main>
);

image.png


3.3 className

html中直接定义class类名不同,jsx中定义类名要通过className属性,这是因为我们写的代码最终会被转成js,而classjs的关键字,如果在jsx中直接用class作为类名会导致冲突 现在我们给header元素添加一个类名

const header = (
  <header className="header">
    <h1>Hello JSX</h1>
  </header>
);

再给这个类名添加样式

.header {
  background-color: darkcyan;
}

image.png


3.4 注入数据给jsx

和前面组合多个JSX类似,我们可以还可以将别的变量注入到jsx

3.4.1 注入string

可以将string注入到jsx

// header 数据
const author = 'Plasticine';

const header = (
  <header className="header">
    <h1>Hello {author}</h1>
  </header>
);

image.png


3.4.2 注入number

number注入到jsx

// main 数据
const likesCount = 666;

const main = (
  <main style={{ backgroundColor: 'skyblue', fontSize: '24px' }}>
    <p>
      Lorem ipsum dolor, sit amet consectetur adipisicing elit. Facilis
      animi, tempora tenetur eos commodi, veritatis atque qui obcaecati
      reiciendis fugit nemo repellat architecto, impedit dolor aliquam
      saepe illum ut nobis?
    </p>
    <p>likes: {likesCount}</p>
  </main>
);

image.png

3.4.3 使用js表达式

事实上我们还可以在jsx中使用js表达式

const main = (
  <main style={{ backgroundColor: 'skyblue', fontSize: '24px' }}>
    <p>
      Lorem ipsum dolor, sit amet consectetur adipisicing elit. Facilis
      animi, tempora tenetur eos commodi, veritatis atque qui obcaecati
      reiciendis fugit nemo repellat architecto, impedit dolor aliquam
      saepe illum ut nobis?
    </p>
    <p>likes: {likesCount}</p>
    <p>1 + 1 = {1 + 1}</p>
  </main>
);

image.png


3.4.4 注入数组

可以直接将数组注入到jsx

// footer 数据
const partners = ['mike', 'jack', 'plasticine'];

const footer = (
  <footer>
    <p>Copyright 2022</p>
    <p>{partners}</p>
  </footer>
);

image.png 但是很明显能看到,数据全都被放在一行显示了,不是很好看,我们可以利用数组对象的map方法,将partners字符串数组转成jsx元素数组

const partners = ['mike', 'jack', 'plasticine'];
const partnersFormatted = partners.map((partner) => <li>{partner}</li>);

image.png 可以看到也渲染成功了, 但是控制台中会有警告 image.png 这里我猜测和vuev-for一样,对于数组的渲染,是需要一个key属性的,这涉及到底层对于元素更新的diff算法的优化 那么我们直接加上key属性就行了

const partnersFormatted = partners.map((partner) => (
  <li key={partner}>{partner}</li>
));

这样就没有警告了


3.4.5 注入对象

对象就不能像数组那样直接注入了

// footer 数据
const partnerInfo = {
  mike: '178cm',
  jack: '180cm',
  plasticine: '200cm',
};

const footer = (
  <footer>
    <p>Copyright 2022</p>
    <p>{cooperativePartner}</p>
    <p>{partnerInfo}</p>
  </footer>
);

image.png 我们应当用对象中的具体值

const footer = (
  <footer>
    <p>Copyright 2022</p>
    <p>{cooperativePartner}</p>
    <p>mike: {partnerInfo.mike}</p>
    <p>jack: {partnerInfo.jack}</p>
    <p>plasticine: {partnerInfo.plasticine}</p>
  </footer>
);

image.png

3.5 JSX中的注释

JSX中,注释也要像变量一样注入进去,用{}包裹

const foo = (
  {/* foo comment */}
  <p>foo</p>
)

总结

第一天接触react,我们学习了:

  • 如何创建和组合jsx元素
  • 如何在jsx元素上使用内联样式
  • 如何给jsx元素添加类名
  • 如何注入数据到jsx元素中

可以感觉到,react的开发更加像是原生开发,也可以看出jsx的灵活性很强 今天只是简单体验上手一下react,使用cdn的方式可以明显感觉到开发体验并不好,比如没有语法提示,后面我们会通过脚手架的方式搭建react项目以及创建react组件,组件比jsx具有更强大的功能