从 JSX 谈起,一起探探 React 框架的学习(新手指南向)

1,200 阅读7分钟

写在前面:很多前端自学者在完成了 HTML/CSS/JavaScript 三大语言的学习之后,往往容易(比如我)产生迷茫,不知道下一步该学什么,怎么学。

我想,在掌握扎实的语言基础后,相当有必要开始进行前端主流框架的学习。接下来我将把我自己的学习过程和学习指南做分享,希望多和掘金社区的朋友们交流。

第一个问题:什么是 React JSX?

w3cschools.com 给出的介绍是:

  1. JSX stands for JavaScript XML.

  2. JSX allows us to write HTML in React.

  3. JSX makes it easier to write and add HTML in React.

JSX 的全称是:JavaScript XML

将 JavaScript XML 分别来看:

1. JavaScript :属于 HTML 和 Web 的编程语言,对网页行为进行编程,和定义网页内容的 HTML、定义网页格式的 CSS、一起被人熟知的定义网页动作的语言

2. XML:  可扩展标记语言(Extensible Markup Language),XML 可用来传输和存储数据,其焦点是数据的内容,是对 HTML 的补充而不是替代

个人理解:JSX 是一种允许在 JavaScript 中混合写入类似于 HTML 的语法规定,便于程序员使用 React 库进行网页开发,在很多常见的场景下,JSX 看起来像 HTML,行为也像 HTML。但是,它最终是被设计为翻译成 JavaScript

第二个问题:为什么是 React JSX?

从本质上看,JSX 仅仅只是 React.createElement(component, props, ...children)函数的语法糖。也就是说这种语法对语言的功能没有影响,但是更方便程序员使用。语法糖让程序更加简洁,有更高的可读性。

我们可以在 React 中使用 JSX 来替代常规的 JavaScript,JSX 的使用不是必须的,但是如果不使用 JSX 则会带来很大的不便。

React 认为渲染逻辑本质上与其他 UI 逻辑内在耦合,比如,在 UI 中需要绑定处理事件、在某些时刻状态发生变化时需要通知到 UI,以及需要在 UI 中展示准备好的数据。

React 并没有采用将标记与逻辑进行分离到不同文件这种人为地分离方式,而是通过将二者共同存放在称之为“组件”的松散耦合单元之中,来实现关注点分离。

React 不强制要求使用 JSX,但是大多数人发现,在 JavaScript 代码中将 JSX 和 UI 放在一起时,会在视觉上有辅助作用。它还可以使 React 显示更多有用的错误和警告消息。

JSX 有如下优点:

  1. 类 XML 语法容易接受,结构清晰
  2. 增强 JavaScript 语义
  3. 抽象程度高,屏蔽 DOM 操作,跨平台
  4. 代码模块化

为了要使用 JSX 语法,我们必须要引入 babel 的 JSX 解析器,把 JSX 转化成 JS 语法,这个工作会由 babel 自动完成。同时引入 babel 后,我们就可以使用新的 es6 语法,babel 会帮我们把 es6 语法转化成 es5 语法,兼容更多的浏览器。

第三个问题:怎么配置实践 React JSX 所需的环境(当然包括了其他 React 实践所需要的部分环境)?

  1. 安装 Node.js

    进入 Node.js 官网选择适合自己操作系统的最新的版本下载,下载完成后在命令行中输入: node -v

     如果得到版本号证明下载成功,当前最新版本 v12.16.1
    
  2. 安装 webpack

    命令行中键入:npm install webpack -g

    下载完成后在命令行中输入:webpack -v

     如果得到版本号证明下载成功,当前最新版本 4.42.0
    
  3. 使用 webpack 初步建立一个项目

    1. 新建文件夹,使用 cd 命令跳转至该文件目录下,运行 npm init -y快速初始化项目

    2. 在该文件夹下新建 src 和 dist 文件夹,在 src 目录下创建 index.html 文件和 index.js 文件

    3. 返回上一层文件夹,新建 webpack.config.js 文件,并做配置如下:

      module.exports = {
          mode:'development'
      }
      //此处没有进行打包入口文件的配置,因为在此版本下的 webpack 中默认的打包入口路径是 src->index.js
      
      
  4. 在 package.json 中增加 dev 配置:

    "scripts": {        
        
        "dev": "webpack-dev-server --open --port 3000 --hot --process --compress --host 127.0.0.1"
    }
    
     至此可以在该目录下使用命令行 `npm run dev `在的配置对应的端口上运行网页,如果各工具版本无冲突,配置正确,那么应该会显示如下内容:
    
    > webpack-base@1.0.0 dev C:\Users\Dongshufeng\webpack-base
    > webpack-dev-server --open --port 3000 --hot --process --compress --host 127.0.0.1
    
    i 「wds」: Project is running at http://127.0.0.1:3000/
    i 「wds」: webpack output is served from /
    i 「wds」: Content not from webpack is served from C:\Users\Dongshufeng\webpack-base
    i 「wdm」: wait until bundle finished: /
    i 「wdm」: Hash: 9d2c7c98d724d42724c0
    Version: webpack 4.42.0
    Time: 1681ms
    Built at: 2020-03-21 11:04:03
    
  5. 接下来要是启用 JSX 语法的配置

    安装 babel 插件

    运行npm i babel-loader @babel/core @babel/plugin-transform-runtime @babel/runtime -D

    运行 npm i @babel/preset-env @babel/plugin-proposal-class-properties -D

    安装能够识别转换JSX语法的包,就是将JSX转化为JavaScript @babel/preset-react

    运行npm i @babel/preset-react -D

    添加 .babelrc 配置文件

    {
    "presets": ["@babel/preset-env", "@babel/preset-react"],
    "plugins": ["@babel/plugin-transform-runtime", "@babel/plugin-proposal-class-properties"]
    }
    

    添加babel-loader配置项:

    module: { //要打包的第三方模块
        rules: [{ 
            test: /\.js|jsx$/, use: 'babel-loader', 
            exclude: /node_modules/ 
        }]
    }
    

至此我们成功地从零开始配置了可供 JSX 运行的环境。在此过程中:为提升 npm 的下载速度,可以尝试使用 cnpm 或设置淘宝镜像 npm config set registry https://registry.npm.taobao.org

一定要注意各环节版本上的差异,细心且耐心地进行下载和配置。

第四个问题:如何使用 JSX?

首先可以对比一下使用与不使用 JSX 的区别:

使用 JSX:

import React from 'react'
import ReactDOM from 'react-dom'
const mydiv =
 <div id = "mydiv" title = "div aaa">
    this is a div element    
 </div>
ReactDOM.render(mydiv,document.getElementById('app'))

不使用 JSX:

import React from 'react'
import ReactDOM from 'react-dom'
const mydiv = 
React.createElement('div',{id :'mydiv',title : 'div aaa'},'this is a div element')
ReactDOM.render(mydiv,document.getElementById('app'))

运行后可以发现:JSX 的使用与否,表面上并不影响页面的呈现效果,但是二者的可读性和易用性是不可同日而语的

那么如何使用 JSX?

1. JSX 必须被严格闭合

在 HTML 中不严格的闭合可能不会造成严重后果(当然也应该闭合标签),但是在 JSX 中,不严格的闭合会引起编译器报错:

    (property) JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>

    JSX element 'div' has no corresponding closing 

2. JSX 标签必须要有一个父级元素

也就是说,类似于 HTML DOM 树,必须有一个根节点,下面的这种用法是错误的,因为两个标签是并列的关系且没有父级元素:
    const mydiv =
    <div id = "mydiv" title = "div aaa">
    this is a div element    
    </div>
    <h1>this is a h1 tag</h1>
这种情况下会报错:
    JSX expressions must have one parent element.ts(2657)

3. 遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;遇到代码块(以 { 开头),就用 JavaScript 规则解析。以下是一些常见的使用方法

  1. 使用变量

    import React from 'react'
    import ReactDOM from 'react-dom'
    const mydiv = <div id = "mydiv" >
     the number is: {3+3}    
     </div>
     
    ReactDOM.render(mydiv,document.getElementById('app'))
    
    
  2. 使用数组(这里的代码是没有问题的,但是找不到原因为何在 .md 文件中从 </h2>开始显示颜色异常)

    JSX 允许在模板中插入数组,数组会自动展开所有成员;数组名[i]会选定数组中的第个i元素:

    import React from 'react'
    import ReactDOM from 'react-dom'
    var myarr = [
        <h1>this is h1</h1>,
        <h1>this is h2</h2>,
    ];
    ReactDOM.render(<div>{myarr[0]}</div>,
    document.getElementById('app'))
    
    
  3. JSX 的条件判断

    JSX 中没有条件判断,可以使用三目运算符

    import React from 'react'
    import ReactDOM from 'react-dom'
    var i = 1;
    ReactDOM.render(
    <div>
        <h1>{i == 1?'true':'flase'}</h1>    
    </div>,
    document.getElementById('app')
    )
    

4.CSS的指定

不同于 HTML 的是,在 JSX 中,style 属性不能包含 CSS,而是引用一个包含样式信息的对象:

import React from 'react';
import ReactDOM from 'react-dom';

class MyHeader extends React.Component {
  render() {
    return (
      <div>
      <h1 style={{color: "red"}}>Hello Style!</h1>
      <p>Add a little style!</p>
      </div>
    );
  }
}
ReactDOM.render(<MyHeader />, document.getElementById('app'));

以上是关于 React 和在 React 中书写 JSX 的一点心得,希望大家多拍砖!