2 Star 1 Fork 0

ecnuzlwang / react-cesium-es5

Create your Gitee Account
Explore and code with more than 6 million developers,Free private repositories !:)
Sign up
This repository doesn't specify license. Without author's permission, this code is only for learning and cannot be used for other purposes.
Clone or download
Cancel
Notice: Creating folder will generate an empty file .keep, because not support in Git
Loading...
README.md

#####概述

一个常规的React项目通常用ES6开发,然后用babel从ES6编译到ES5,最后再用webpack整合各个文件和其对应的依赖项,打包成单个js文件使用。

但是这样做也存在问题,如果当前端代码与后台数据和逻辑紧密关联,调试的时候会比较麻烦。而且目前没有浏览器支持ES6的语法,所有ES6的项目需要编译成ES5才能运行。

本文的目的是建立一种方法,达到以下目的:

  • 不使用webpack将代码打包成单个js
  • 实现单个文件(包含ES6JSX语法)的编译
  • 使用ES5的React.creatClass方法创建React组件
  • 保留ES6和JSX语法中方便快捷的语法功能(比如解构赋值,数组对象展开符号...)

最后的目录结构

react-cesium/
  node_modules/     #开发时依赖模块
  package.json      #项目配置文件,用于开发时的包管理等
  css/              #样式文件,无需编译,直接用css语法编写
  html/             #html文件,无需编译,添加对应js文件即可
  js/               #编译好的ES5文件,多个文件相互独立,无压缩,也可以直接修改(但是不建议)
  src/              #源码文件,内有JSX和ES6,需编译,编译好的文件存放在js/文件夹下
    cesium/
        CesiumGlobe.js
        ...
    App.js
    ...

下面我们来讲讲ES6传统JavaScript的差别,同时把React ES6的项目调整成传统的JavaScript项目。

#####依赖项

ES6将每个依赖项作为一个模块加载到JavaScript文件中,用import导入模块,用export导出模块。比如,导入React依赖:

//导入外部模块
import React, {Component} from 'react';
//导入自己编写的模块
import CesiumGlobe from "./cesium/CesimGlobe";

传统的JavaScript将所有的依赖项通过<script>标签加载进来,每一个依赖项成为一个全局变量。比如,加载Cesium库和React:

//导入外部模块
<script src="./node_modules/cesium/Build/Cesium/Cesium.js" charset="utf-8"></script>
<script src="./node_modules/react/dist/react.min.js" charset="utf-8"></script>
//导入自己编写的模块
<script type="text/javascript" src="./lib/cesium/CesiumGlobe.js"></script>

两者都有优缺点,ES6的语法可以实现局部模块的调用,不会让模块和模块内部的变量成为全局变量,避免全局污染,但是importexport的语法需要通过babel和webpack编译打包才能用在浏览器中。传统JavaScript的文件不需要编译直接使用,比如导入了Cesium,就直接使用Cesium.方法名调用方法,Cesium本身是一个全局变量。

#####生成组件

React项目中以组件的形式封装功能和视图。ES6中,实现用class 组件名 extends React.Component{}的方法继承React的组件类,然后编写相关的函数和渲染功能:

class InputControlES6 extends React.Component { 
  constructor(props) {
    super(props); 
    // 设置初始状态值,在constructor构造函数中
    this.state = {
      text: props.initialValue || 'placeholder' 
    };
    // 组件内部方法需要手动bind到this对象中
    this.handleChange = this.handleChange.bind(this); 
  } 
  handleChange(event) {
    this.setState({ 
      text: event.target.value
    });
  } 
  render() {
    return (
      ...
    );
  }
}

ES5中通过React.createClass()方法返回一个组件类,赋值给一个变量,这个变量就作为这个组件类存在。

var InputControlES5 = React.createClass({
  // 设置初始状态值,用getInitialState方法
  getInitialState: function() {
    return {
      text: this.props.initialValue || 'placeholder' 
    };
  },
  //方法无需bind到this上
  handleChange: function(event) {
    this.setState({
      text: event.target.value
    });
  },
  render: function() {
    return (
        ...
      );
    }
});

#####JSX

JSX是React的新发明,将HTML和JavaScript结合使用,全都写在JS代码中。个人认为,一开始你可能会有些不适应这样的写法,但是很快你就会依赖上JSX,因为他实在是太方便了。但是浏览器同样不支持JSX,所以还是需要用Babel编译成传统的JavaScript(这不是ES6和ES5的不同,是JSX这种语法对浏览器的不兼容)。 相同的一段代码,用JSX写是这样的:

<div>
    Type something:
    <input onChange={this.handleChange}
           value={this.state.text} />
</div>

用传统的JavaScript结合React.createElement方法写是这样的

React.createElement(
    'div',
    null,
    'Type something:',
    React.createElement('input', { onChange: this.handleChange,
        value: this.state.text })
);

#####如何将ES6和JSX编译成ES5 Babel这个工具是目前被广泛使用的前端编译工具,能将ES6,JSX,TypeScript,CoffeeScript等语法的JS脚本编程成传统的JavaScript。 要使用Babel,你需要在电脑上安装node和npm,先用npm下载babel的依赖:

# Babel命令行工具
npm install --save-dev babel-cli
# ES2015转码规则
$ npm install --save-dev babel-preset-es2015

# react转码规则
$ npm install --save-dev babel-preset-react

# ES7不同阶段语法提案的转码规则(共有4个阶段),选装一个
$ npm install --save-dev babel-preset-stage-0
$ npm install --save-dev babel-preset-stage-1
$ npm install --save-dev babel-preset-stage-2
$ npm install --save-dev babel-preset-stage-3

Babel的配置文件是.babelrc,存放在项目的根目录下。使用Babel的第一步,就是配置这个文件。 该文件用来设置转码规则和插件,基本格式如下。

  {
    "presets": [
      "es2015",
      "react",
      "stage-2"
    ],
    "plugins": []
  }

安装配置完成后,使用命令行编译单个文件或者文件夹:

./node_modules/.bin/babel src -d lib

上面的命令将src文件夹下的代码都编译到lib文件夹中。

使用babel会自动识别代码中不是传统JavaScript的部分,编译成传统JavaScript,最后生成的代码没有打包成一个文件,还是原来的目录结构。只要用<script>标签将每个文件引入html文件,就可以使用了。

当然,你如果觉得ES6和JSX的语法不方便,可以直接使用ES5编写代码,Babel会忽略ES5的语法,不编译也不改变,没有什么影响。

#####为什么要保留ES6和JSX,而不是直接使用ES5开发

我们来看几个ES6和ES5比较的例子:

######解构赋值

//ES6
const {homeView={},polylines={},isMobile=false,sceneMode=2} = this.state;
//ES5
var _state = undefined.state,
    _state$homeView = _state.homeView,
    homeView = _state$homeView === undefined ? {} : _state$homeView,
    _state$polylines = _state.polylines,
    polylines = _state$polylines === undefined ? {} : _state$polylines,
    _state$isMobile = _state.isMobile,
    isMobile = _state$isMobile === undefined ? false : _state$isMobile,
    _state$sceneMode = _state.sceneMode,
    sceneMode = _state$sceneMode === undefined ? 2 : _state$sceneMode;

上面的代码,将this.state对象中的homeViewpolylinesisMobilesceneMode这四个成员变量赋值给同名的独立变量,如果this.state中没有值,就给一个默认值。比如如果this.state.sceneMode不存在,就默认为2。 ######箭头函数

//ES6
const newArr = arr.map(item=>item+1);
//ES5
var newArr = arr.map(function (item) {
	return item + 1;
});

上面代码遍历arr数组,返回一个新数组newArr,ES6支持箭头函数,可以省去functionreturn等关键字。

######数组或对象展开

//ES6
const newArr3 = [...newArr2,1,3,4,5];
const newObj = {...obj,key:value};

//ES5
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

var newArr3 = [].concat(_toConsumableArray(newArr2), [1, 3, 4, 5]);
var newObj = _extends({}, obj, { key: value });

上面代码是ES6中非常好用的功能,用...将数组或者对象展开,在后面添加多个新的数组元素或者对象的键值对。常用于React中setState方法。展开对象的时候,如果后面添加的key与原对象中的key相同,就会冲掉原来的值,换上新的值。

######JSX的魅力

个人认为JSX的魅力是数据驱动视图变化,不需要添加太多人工的逻辑。举个例子,比如一个Cesium的指南针,要实现转盘旋转时,地球跟着旋转。看似简单的逻辑,需要用到鼠标按下、移动和抬起事件,要用CSS中的tranform特性旋转图标。下面的代码是React的render中的逻辑,每次this.state有值更新,就会重新调用render:

const rotationMarkerStyle = {
	transform: 'rotate(-' + this.state.orbitCursorAngle + 'rad)',
	WebkitTransform: 'rotate(-' + this.state.orbitCursorAngle + 'rad)',
	opacity: this.state.orbitCursorOpacity
};

const outerCircleStyle = {
	transform: 'rotate(-' + this.state.heading + 'rad)',
	WebkitTransform: 'rotate(-' + this.state.heading + 'rad)',
	opacity: ''
};
<div className={Styles.compass} title ={description} onMouseDown ={this.handleMouseDown} onDoubleClick ={this.handleDoubleClick} onMouseUp ={this.resetRotater}>
    <div className={Styles.outerRing} style={outerCircleStyle}></div>
    <div className={Styles.innerRing} title='点击拖拽旋转指南针'></div>
    <div className={Styles.rotationMarker} style={rotationMarkerStyle}></div>
</div>

上面的JSX中,this.state.headingthis.state.orbitcursorAngle是随着鼠标点击变化的,每一次变化,style的值也跟着变化,实现旋转指南针指针的功能。

#####总结

为了实现使用传统web项目的目录结构,不打包js文件,我们需要牺牲一些ES6的新特性(比如importexport方便的导入导出模块),不过大部分方便的功能是可以保留的。

Comments ( 0 )

Sign in for post a comment

About

用es5开发react和cesium应用的项目模板 spread retract
JavaScript
Cancel

Releases

No release

Contributors

All

Activities

load more
can not load any more
JavaScript
1
https://gitee.com/ecnuzlwang/react-cesium-es5.git
git@gitee.com:ecnuzlwang/react-cesium-es5.git
ecnuzlwang
react-cesium-es5
react-cesium-es5
master

Search