为了尽快上手React,我们先通过一个实际例子,增加你的感性认识。我们将使用React先构建一个简单的Monkey代码编译器,没有感性认识的知识讲解都是bullshit,就像你没摸过水就跟你讲解游泳理论一样。即使你对Reactjs的运用一无所知,通过亲手把代码敲一遍,并看到实践的效果,你内心也自动会对Reactjs有了较为深刻的认知。
首先你需要自行安装好node.js,React本身并不需要Node.js,但开发中需要的很多工具和模块需要Node.js的支持,特别是我们需要NodeJS的npm 模块安装工具。安装好NodeJS后,先运行以下命令:
npm install --global create-react-app
create-react-app 是通过npm模块发布的一个安装包,通过该工具,我们能快速创建一个reactjs项目。接着执行以下命令:
npm install --save react-bootstrap
上面的命令用来安装试用与react框架的boostrap UI控件库,我们将使用它来开发我们Monkey编程语言的IDE。完成上面的安装后,我们就可以创建第一个Reactjs项目了,运行以下命令:
create-react-app monkey_compiler
这个命令会在本地目录创建一个名为monkey_compiler的目录,它已经是一个可运行的reactjs项目,我们在此基础上通过修改或添加若干文件,就可以完成相应的React应用开发,避免大量繁琐的配置工作。接着我们执行:
cd monkey_compiler
npm start
上述命令执行后,命令会启动一个开发模式的服务器,同时会自动调用浏览器打开一个页面,页面指向本地地址http://localhost:3000, 基本情况如下图:
接下来,我们将进入MonKey语言IDE的开发,我们将利用reactjs组件化开发的特点,通过乐高式搭积木的方式,逐步开发出一个功能丰富的页面IDE出来,我们先为项目增加一个新的react组件。你可以把react组件想象成一块砖头,整个react最终项目想象成一座大楼,我们通过砖头间的排列组合就可以搭建出我们想象中的大楼,更重要的是,这些砖头可以重用,你可以在这里搭建‘央视大裤衩’,也可以用相应的砖头搭建‘悉尼歌剧院’,由此可见react框架通过组件化的方式构建项目的模式是相当灵活且强大的。
在生成的monkey-compiler项目中,有一个目录叫src/,该目录用于存放项目的所有代码文件,在开发过程中,我们只要关注src目录中的内容,打开其中的index.js,可见内容如下:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
其中的App 就是一个组件,它被加载后,效果就是我们前面看到的那样。我们稍作修改,定义一个新组件,修改后代码如下:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import MonkeyCompilerIDE from './MonkeyCompilerIDE';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<MonkeyCompilerIDE />, document.getElementById('root'));
registerServiceWorker();
我们把App换成了MonkeyCompilerIDE,我们先把代码的具体含义放一放,先看看如何增加一个React组件,在src目录下创建一个新的代码文件叫MonkeyCompilerIDE.js,并在里面添加如下代码:
import React , {Component} from 'react'
import * as bootstrap from 'react-bootstrap'
class MonkeyCompilerIDE extends Component {
constructor(props) {
super(props)
}
render () {
let textAreaStyle = {
height: 480
};
return (
<bootstrap.Panel header="Monkey Compiler" bsStyle="success">
<bootstrap.FormGroup>
<bootstrap.FormControl componentClass = "textarea"
style={textAreaStyle}
placeholder="Enter your code" />
</bootstrap.FormGroup>
<bootstrap.Button bsStyle="danger">
Lexing
</bootstrap.Button>
</bootstrap.Panel>
);
}
}
export default MonkeyCompilerIDE
由于我们使用到了boostrap控件库,因此需要从外部引用相关的css样式文件,回到根目录,进入public目录,打开index.html,在其头部添加如下代码:
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css">
代码解析一会再说,完成上面代码后,先通过命令npm start看看运行效果:
这就是我们想要的Monkey编程语言开发所用的IDE,相当于Visual Studio或Eclipse,当然现在看起来它太简陋,我们后续会慢慢增强其功能。在文本框中键入Monkey 代码,点击下面按钮,我们就可以开始编译原理算法中的第一步:词法解析,这是我们后续章节要详细讲解的内容。回过头来,我们先解析一下刚完成的组件代码。
你或许可以感觉到,我们用来开发组件的代码不像是前端开发常用的javascript,组件通过class关键字来定义,而且用constructor函数作为类的初始化函数,这些代码看起来似乎与常用的java语言很相像了。这些代码遵循的标准叫ES6,是最新版的js代码语法格式,实际上当前主流浏览器并不支持这种格式代码的解析和执行,但为何他们仍然能运行在各大浏览器中呢?这是因为在Reactjs框架中内嵌了一个小型编译器叫Babel,它会把上面代码编译成浏览器能够解析并执行的常用E5标准的javascript代码,由此可见,掌握编译原理的重要性可见一般了吧!
在index.js中,我们使用import将新组件导入,以便替代原有的App组件。在MonkeyCompilerIDE.js中,第一行我们从react库中引入React和Component两个组件:
import React , {Component} from 'react'
import * as bootstrap from 'react-bootstrap'
第二行我们把react-bootstrap组件库中所有组件全部加载进来,并给予一个统称叫bootstrap,如果我想使用其中的一个组件例如Button,(上面左下角的红色按钮就是由Button组件创建的),那么我们可以通过bootstrap.Button来引用,这跟我们很类似与从一个类中引用它的公有成员变量。
Component组件是所以组件的基类,如果你熟悉java的话,该组件相当于java所有类的父类Object。因此MonKeyCompilerIDE组件的父组件就是Component。在React出现之处,组件的创建方法是通过调用React.createClass来创建组件,现在网上或一些书籍对React的讲解还是基于这种办法,我们必须意识到,这种办法是过时的办法。这两种方式的差异显示出React框架在开发方法论上的显著进化,我们现在使用的是类似于java那样面向对象的开发方式,而React.createClass这种创建组件的方式其实是类似于C语言那样的,面向过程的开发方式。
在上面的代码中我们导入了Component类有被使用到,但导入的React组件却没有被使用到,你可以尝试把第一行中的React给删除然后再加载页面,你就可以看到错误信息:’React’ must be in scope when using JSX。
这里的JSX是一个比较抽象的概念,React的初学者很容易被这个概念搞得糊里糊涂,就像C语言的初学者总会被‘指针’搞得二和尚摸不在头脑一样。什么是JSX呢,在render()函数中,我们通过return返回了一堆类似HTML代码似的东西:
<bootstrap.Panel header="Monkey Compiler" bsStyle="success">
<bootstrap.FormGroup>
<bootstrap.FormControl componentClass = "textarea"
style={textAreaStyle}
placeholder="Enter your code" />
</bootstrap.FormGroup>
<bootstrap.Button bsStyle="danger">
Lexing
</bootstrap.Button>
</bootstrap.Panel>
是的!上面这坨看似与HTML代码非常类似的代码块就叫JSX.它们格式跟HTML很像,但他们不是HTML, 因为它其中包含了HTML规范没有的标签,例如bootstrap.Panel, 其实<>这对尖括号中包含的东西都叫组件而不是标签,由于JSX的形式与HTML实在太像了,所以初学者对它很容易感觉迷茫和困惑。
所谓JSX,它本质是javascript语法的扩展,也就是javascript extension。JSX中,JS代表javascript, X代表 eXtension. 上面那一坨看似HTML的代码其实是以HTML标签化形式来编写的javascript代码,首先要注意上面那坨代码中,有很多元素是HTML规范中没有的。
在React创建之初,人们对这种把javascript代码以HTML标签似来写的方式非常反感。因为这实在太容易引起认知混乱了。但是经过一段时间后,业界发现这种办法很实用。因为原来前端开发的基本思路是,用HTML来表示内容,用CSS来表示样式,用Javascript来定义交互行为,这是三种不同的语言,三种不同的设计逻辑,并且它们往往分布在不同的文件里,这就使得设计逻辑分成了多个不同的部分和层次,因此会带来项目理解和管理上的很多麻烦。
一个组件实际上是一个逻辑上有高度耦合性的独立性个体。如果按照原有方式,那意味着需要把一个原则上不可分的个体分成了三部分(HTML,CSS,Javascript)。既然是一个像原子一样不可再分的单元,那么设计上就应该把所有逻辑整合在一起。我们看到,在render函数中,我们还定义了一个textAreaStyle的对象,不难看出,它实际上承担了原来CSS的作用,也就是说,在JSX中,我们可以统一用javascript语言来代替原来需要用HTML和CSS来实现的功能,于是这样,原来分开三部分的设计逻辑在这里就统一起来了。
JSX是reactjs前端开发的核心功能所在,对初学者而言,它不好理解,但只要随着我们项目的深入,练习多了后,你慢慢的会掌握和消化它。下一节我们将在本节的基础上,进入代码编译的第一步:词法解析。
更详细的讲解和代码调试演示过程,请点击链接,如果点击页面没有发现相应视频,那说明视频还在审批中,敬请期待。
更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号: