听风是风

学或不学,知识都在那里,只增不减。

导航

从零开始的react入门教程(一),让我们从hello world开始

壹 ❀ 引

按照之前的计划,从这个月开始,我将由浅至深更新一些react相关的技术博文。由于我目前也是react新手一名,所以文章本质上也算自己学习历程的记录,倘若这些文章能帮助到一些人那就再好不过了。那么这一篇文章就作为一个新的开端,从零开始一起变得更强吧,本文开始。

贰 ❀ 准备工作

在学习基础知识之前,我们可以在本地搭建并运行一个react应用,便于后续学习时例子效果预览。请先确保电脑已成功安装node.js

比如我的学习项目都喜欢丢在D盘,所以可以在D盘新建一个job文件夹(名字随你喜欢),进入job目录,打开终端,这里我用的git终端。执行复制npx create-react-app my-app命令并回车,等待安装完成。

等到出现Happy hacking!,说明下载完成。

之后就可以看到job目录下多了一个my-app文件夹,这就是我们下载的react应用了。双击进入my-app目录,再进入src文件夹,删除所有文件之后,创建index.css与index.js文件,像这样:

用编辑器(我用的vscode)打开my-app项目,在前面创建的index.js中拷贝如下代码:

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";

ReactDOM.render(<h1>Hello, world!</h1>, document.getElementById("root"));

注意,由于react的jsx语法特性,我们可以在js中编写html,所以习惯格式化代码的同学可能会将代码格式出问题,毕竟js中无法识别HTML。对于这个问题我们可以通过切换编辑器语言模式来解决,点击编辑器右下角的语言,如下图:

输入java可以看到下方有个javaScript React,选择此语言,再格式化你就发现支持jsx语法了。

每次点击右下角切换语言也比较麻烦,好的做法是给选择语言模式直接配置一个键盘快捷方式。点击编辑器左上角的文件--->首选项--->键盘快捷方式,之后输入语言,可以看到有一个更改语言模式。点击左边的修改图标,输入你想要的快捷方式,保存即可,这里我用快捷键是ctrl+k,之后就可以通过快捷键快速切换语言模式了。

ok,简单说了下语言模式的事情,现在我们可以通过ctrl+~打开编辑器的终端,然后输入npm start并回车。

你会发现浏览器自动打开了一个页面,这就是我们本地开发环境成功跑起来了。使用本地环境的好处是,我们每次修改并保存代码,页面都会自动刷新,而此时页面赫然显示了一句 Hello, world!,恭喜你,到这里我们成功创建了第一个属于自己的应用,虽然它目前还很简单,但通过后面的学习,我们来一起让它变得更酷!

叁 ❀ jsx基础

按照以往传统的开发习惯,dom结构我们一般写在html中,而js文件会负责业务相关逻辑,但站在react的角度,我们会在js中编写html相关代码,如果你有了解vue的jsx语法,我想你会更快接受这一设定,之前没了解也不用担心,我们来解释下文章开头代码做了什么。

让我们打开项目的public文件,查看index.html,可以看到代码中有一个id为root的div盒子,结合我们前面例子中ReactDOM.render编译的内容,其实不难理解,render只是将需要编译的dom,塞到了root的盒子中,这种指定应用容器以及编译内容的思想其实与vue以及angularjs是相似的,只是现在html换了个地方编写而已。

jsx属于JavaScript的语法拓展,事实上它既不是标签语法,也不是普通字符串(官方称呼react元素),但它具备JavaScript全部功能。我们编写的jsx其实会被bable转译成React.createElement()调用(vue也有类似的createElement方法),比如下面这段代码是等效的:

const ele = <h1 className="echo">Hello, world!</h1>;
// 等同于
const ele = React.createElement(
  "h1", //标签名
  { className: "echo" }, //标签属性
  "Hello, world!" //子节点内容
);

React.createElement()本质上是创建了一个类似于如下的React对象,react会读取并编译这些对象,用它们构建页面dom并实时保持更新:

const ele = {
  type: 'h1',
  props: {
    className: 'echo',
    children: 'Hello, world!'
  }
};

当然这里我们先不用了解的太深,只用知道jsx大致做了什么,以及为什么react中能这么写就足够了,它们的转换过程其实是react元素经过bable转译--->React.createElement()调用--->react对象--->真实dom。而接下来的语法介绍我想大家会十分熟悉。

react元素支持赋予给变量,比如文章开头的例子也可以写成这样:

const ele = <h1>Hello, world!</h1>;
ReactDOM.render(ele, document.getElementById("root"));

当然,react元素支持嵌套,但需要注意的是,如果我们的结构需要换行,官方推荐使用圆括号包裹你的结构,比如:

const ele = (
    <div>
        <h1>Hello World!</h1>
        <h1>My name's echo!</h1>
    </div>
);
ReactDOM.render(ele, document.getElementById("root"));

这样做的好处是能避免代码压缩遇到自动插入分号的陷阱。

在vue开发中,我们习惯使用模板语法{{}}解析变量,表达式,调用方法等等,其实在react中你同样能这么做,比如:

const myName = "echo";
const add = function (a, b) {
  return a + b;
};

const ele = (
  <div>
    <h1>my name is {myName}</h1>
    <h1>{add(2, 2)}</h1>
    <h1>{2 + 2}</h1>
  </div>
);
ReactDOM.render(ele, document.getElementById("root"));

html标签有属性,react元素与标签一样,同样也支持标签属性以及自定义,比如下面的例子:

const img = "https://pic.cnblogs.com/avatar/1213309/20200507225901.png";
const ele = (
  <div>
    <div id="icon">头像</div>
    <img src={img} alt="icon" />
  </div>
);
ReactDOM.render(ele, document.getElementById("root"));

这里需要注意的是,不要在{}外添加引号,如果你需要解析变量,请使用{},如果它只是一个字符串,那么请添加引号,二者选其一添加,两者不要同时使用。

最后,当添加一个jsx结构时只能有一个react根元素,这点与angularjs的自定义指令模板,vue的组件只能有一个根元素情况类似,比如下面这段代码就是错误示范:

const ele = (
  <div>1</div>
  <div>2</div>
);

正确的做法是为这两个元素添加一个共有的根元素:

const ele = (
  <div>
      <div>1</div>
      <div>2</div>
  </div>
);

但请不要将这些jsx的结构理解成react组件,它们只是一些react元素构成的代码块,组件会有专门的方式去创建,这个后面会具体介绍,当然组件也会利用react元素来构建必要的dom结构。

肆 ❀ 元素渲染的不变性

按照我们以往的框架使用经验,当模板语法解析的某个变量发生改变时,页面会自动更新这个变量。但在react中,元素渲染都是一次性的,渲染成功后修改变量,页面并不会有改变,请看下面这个例子:

let num = 0;
setInterval(function () {
  num++;
}, 1000);

setInterval(function () {
  //控制台输出num
  console.log(num);
}, 1000);

const ele = <div>{num}</div>;
ReactDOM.render(ele, document.getElementById("root"));

打开控制台,你会发现num在不断自增,而页面结构中解析的num依旧是0,并没有任何变化,这是因为ReactDOM.render就是一次性执行,它只会调用了一次,因此没办法及时更新num,比较直接的办法是可以将render整个过程也包裹在定时器中,比如:

let num = 0;
setInterval(function () {
  num++;
}, 1000);

setInterval(function () {
  //利用定时器不断更新react元素,以及让render重复渲染
  const ele = <div>{num}</div>;
  ReactDOM.render(ele, document.getElementById("root"));
}, 1000);

这样做能达到效果,但直观感受这种做法并不友好,其实在后续文档中,react有提供状态专门用于解决这个问题,当然这都是后话了。

其次,我们虽然用定时器反复执行render,但神奇的是react在每次更新dom时,对比新旧dom结构,并只更新发生变化的部分,打开浏览器控制台,观察dom变化就非常清楚了。这一点相对我之前使用的angularjs,就非常人性化了...

伍 ❀ 总

那么到这里,我们成功在本地搭建了一个属于自己的应用,并了解了react中jsx语法,以及一些常见的用法。学习完这些内容,我们可以利用react元素构建出一些简单的静态页面,虽然现在还未涉及组件概念,当然这些将会在后续文章中展开。

不知不觉又凌晨一点了,这篇文章就先写到这里,那么本文结束。

posted on 2020-10-12 01:09  听风是风  阅读(2501)  评论(12编辑  收藏  举报