# 前端技术介绍

ECMAScript

ECMAScript 是一种不绑定在特定宿主环境,和宿主环境无关的脚本语言定义。简单地说,ECMAScript 描述了语法、语句、关键字、保留字、运算符、类型对象等内容。


ECMAScript 类型

  • ECMAScript有6 种原始类型:

    • undefined
    • null
    • boolean
    • number
    • string
    • symbol (es6新增的数据类型)
  • 引用类型 和其他语言一样,除了最基本的原始类型,其他都是引用类型(包括标准对象和自定义的类型)

  • typeof运算符

typeof 1;                   //number
typeof 'A';                 //string
typeof false;               //boolean
typeof undefined;           //undefined
typeof Symbol()             //symbol
typeof null;                //object
typeof {};                  //object
typeof (function(){});      //function
typeof new (function(){});  //object

你也许会好奇,为什么typeof null => object。 实际上它是JavaScript最初实现中的一个错误,然后被ECMAScript沿用了。现在,null被认为是对象的占位符,从而解释了这一矛盾,但从技术上来说,它仍然是原始值。


ECMAScript 对象

在 ECMAScript 中,所有对象并非同等创建的。一般来说,可以创建并使用的对象有三种:

  • 内置对象
  • 本地对象
  • 宿主对象

内置对象

ECMA-262把内置对象(built-in object)定义为“由ECMAScript实现提供的、独立于宿主环境的所有对象,在ECMAScript程序开始执行时出现”。这意味着开发者不必明确实例化内置对象,它已被实例化了。ECMA-262只定义了三个内置对象 Global Math JSON (它们也是本地对象,根据定义,每个内置对象都是本地对象)。

  • Math 通过它来做数学上的运算,但它不是一个函数对象,因此,无法被当作函数和构造函数调用。换句话说:不能new Math()Math()
  • GlobalMathJSON不同,Global对象并没有一个Global的命名空间前缀,Global是全局对象的一个代称,指的是在全局作用域中的对象,全局对象本身可通过 this 操作符在全局作用域中获得。 eval() isNaN() parseInt() encodeURI() encodeURIComponent() 等都是全局对象上的方法。不过像setTimeout()setInterval却是宿主对象Window上的方法。可以通过查阅JS标准库文档获知具体的定义。

本地对象 ECMA-262 把本地对象(native object)定义为“独立于宿主环境的 ECMAScript 实现提供的对象”。它们包括:

  • 基础对象

    • Object
    • Function
  • 数据类型对象

    • Boolean
    • Number
    • Date
    • String
    • RegExp
  • 集合

    • Array
    • Map & WeakMap
    • Set & WeakSet
  • 错误

    • Error
    • EvalError
    • URIError
    • 等等
  • 控制流和反射

    • Promise
    • Generator
    • Reflect
    • Proxy

宿主对象 所有非本地对象都是宿主对象(host object),即由 ECMAScript 实现的宿主环境提供的对象。所有 BOM 和 DOM 对象都是宿主对象。

  • BOM

    • Window
    • Console
    • Navigator
    • Screen
    • History
    • Location
    • SessionStorage & LocalStorage
    • XMLHttpRequest
    • WebSocket
    • 等等
  • DOM

    • Document
    • Event
    • Table
    • Style
    • Form
    • Canvas
    • 等等

Object

所有引用类型的对象都继承自Object,包括函数对象,字面量定义,宿主对象,内置对象等。它是JavaScript所有对象的超类。

Object函数对象

构造JS Object的函数,本身又是一个函数对象,其定义大致为:

function Object(value){
    //...
}

Object函数对象是Function的实例,变量名为Object,这个对象有很多方法,有许多的方法都是在我们开发过程中使用频率很高的,因此需要单独列出来说一下。

Object函数对象的方法
  • Object.assign(target, ...sources) 复制对象
  • Object.create(prototype,propertiesObject) 根据对象的原型对象创建对象。
  • Object.is(obj1,obj2) 判断两个值是否严格相等。(类似===运算符,但+0不等于-0,NaN等于自己)。
  • Object.getPrototypeOf(object) 获取一个对象的原型对象
  • Object.setPrototypeOf(obj, prototype) 设置一个对象的原型对象

以及下面这些方法,要说清楚这一组方法,需要先搞清楚ES5.1新增的属性描述符(PropertyDescriptor)

  • Object.keys()、Object.values()、Object.entries() 获取对象自身定义的属性名、属性值、键值对数组。
  • Object.getOwnPropertyDescriptor()、Object.getOwnPropertyNames()、Object.getOwnPropertySymbols() 获取对象的属性描述符、属性名以及Symbol属性的数组。
  • Object.freeze()、Object.isFrozen() 冻结对象,冻结之后则该对象永远不可变。不可变的含义是:这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。
  • Object.seal()、Object.isSealed() 密封对象,密封与冻结类似,唯一的区别在于该对象的已有属性可以重新被赋值。
  • Object.preventExtensions()、Object.isExtensible() 阻止对象被扩展,被阻止之后,对象永远不能再添加新的属性。
  • Object.defineProperty()、Object.defineProperties()

PropertyDescriptor

属性描述符,它主要有两种形式:数据描述符和存取描述符。描述符必须是两种形式之一;不能同时是两者。

两种描述符共同的配置

  • configurable 是否可配置,仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变和删除。
  • enumerable 是否可枚举,当它为true时,for ... in、Object.keys()就可以遍历到它

仅数据描述符

  • value 该属性对应的值。
  • writable 该属性是否可写,仅当该属性的 writable 为 true 时,该属性才能被赋值运算符改变。

仅存取描述符

  • get 属性的 getter方法,如果没有 getter 则为 undefined。
  • set 属性的 setter方法,如果没有 setter 则为 undefined。

示例代码

//字面量对象的定义方式
let person = {};
Object.defineProperty(person,"firstname",{
    configurable:false,
    enumerable:true,
    writable:true,
    value:"Xiaoming"
});
Object.defineProperty(person,"lastname",{
    configurable:false,
    enumerable:false,
    writable:true,
    value:undefined
});
for(let key in person) {
    console.log("字面量对象的定义方式:"+key+":"+person[key]);
}

//构造函数的方式
function Person(){
    let fname;
    let lname;
    Object.defineProperty(this,"firstname",{
        configurable:false,
        enumerable:true,
        set:function(newValue){
            fname = newValue;
            console.log("构造函数方式:调用setter");
        },
        get:function(){
            return fname;
        }
    })
}
new Person().firstname = "张三";

//ES6
class PersonClass {
    constructor(){
        // ...
    }
    get firstname() {
        return 'es6方式:调用getter';
    }
    set firstname(value) {
        console.log('setter: ' + value);
    }
}
console.log(new PersonClass().firstname);
对象属性的遍历
  • Object.getOwnPropertyNames() 返回自身的所有属性名(包括不可枚举属性)
  • Object.keys(obj) 返回自身的所有可枚举属性
  • for...in 返回自身的和继承的所有可枚举属性

Function

用来定义函数的构造函数,在JS中,每一个函数实际上都是一个Function对象。句法: new Function ([arg1[, arg2[, ...argN]],] functionBody);

示例说明
function add(a,b){
    return a + b;
}
//等价于

var add = new Function('a','b','return a + b;');

####属性和方法 全局的Function对象没有自己的属性和方法,但是,因为它本身也是函数,所以它也会通过原型链从Function.prototype上继承部分属性和方法。

  • 属性
    • Function.caller 函数的调用对象
    • Function.length 函数的参数数量
    • Function.name 函数的名字
    • Function.prototype 函数的原型对象
  • 方法
    • Function.prototype.apply() 动态指定this对象,并执行。
    • Function.prototype.bind() 指定this对象,并返回函数对象(不执行)。
    • Function.prototype.call() 动态指定this对象,并执行。和apply的唯一区别在于传参方式不一样
    • Function.prototype.toString() (继承自Object,但重写了这个方法。会返回方法的定义)

自定义ECMAScript对象

//构造函数的方式
function Car(color,doors) {
  this.color = color;
  this.doors = doors;
  this.showColor = function() {
    console.log(this.color);
  };
}
//原型方式
function Car(color,doors) {
  this.color = color;
  this.doors = doors;
}
Car.prototype.showColor = function(){
    console.log(this.color);
}

prototype对象和继承

prototype 由Function函数对象所定义,所以每定义一个函数对象,它都有一个prototype属性,不仅如此它还会修改prototype.constructor的值,将其改为新定义的函数对象。换句话说:xfunction.prototype.constructor === xfunction

而prototype本身则是Object的数据类型,由于它是Object的数据类型,它会从Object那继承以下方法,从而每一个被构造的示例都将具有这些方法。

  • constructor
  • hasOwnProperty
  • isPrototypeOf
  • propertyIsEnumerable
  • toLocaleString
  • toString
  • valueOf

令人容易混淆的是: Object和Function这两个函数对象本身又是 Function的实例。我们来看下面的例子,你能猜出他们的结果吗?

Object instanceof Function;
Function instanceof Object;
Function instanceof Function;
Object instanceof Object;

尝试还原一下Function函数的实现。

function Function(){
    var args = [];
    var body = null;
    if(arguments.length) {
        body = arguments.pop();
        args = arguments;
    }
    this.prototype = {
        constructor: this,
        toString : function(){
            var argNames = null;//get argsNames from args
            return "function("+argNames+"){"+body+"}"
        }
    }
}
Function.prototype.constructor = Function;

在做一个测试

function Car() {
  
}

var car = new Car();
//请问这段代码创建了几个对象?

es6-class

示例代码

    class Runnable{
        
        constructor(speed){
            this.speed = speed;
        }
        run(){
            console.log("我可以奔跑");
        }
    }
    class Car extends Runnable{
        constructor(){
            super(100);
            this.color = color;
            this.doors = doors;
            if(Car.createdCount){
                Car.createdCount = Car.createdCount+1;
            } else {
                Car.createdCount = 1;
            }
        }
        static getCount(){
            return Car.createdCount;
        }
        showColor(){
            console.log(this.color);
        }
        get color(){
            return this.color;
        }
        run(){
            console.log("车以每小时"+super.speed+"公里的速度移动");
        }
    }

es6-module

module是什么?

module:模块化,模块化具体是什么意思?模块化主要分为两部分,一个是如何定义对外部的依赖,一个是如何向外部暴露内部的实现。以webpack为例:

向外部暴露接口

//export-a.js
module.exports = {
    a:function(){
        //...
    }
}

定义依赖

var a = required('export-a');//如果是依赖的npm的包required的参数直接给这个包的名字就好。否则按文件处理,按文件存放的相对路径传入相关参数。 .js文件可以省略。

####es6-module 和其他的模块化方案的作用一样,它也是用于处理依赖和模块封装的问题。当然,它是javascript的官方实现。用法也非常的相似。

export关键字 export 命令必须处于模块顶层就可以,不能处于块级作用域内,下面的import命令也是如此。

//写法1
export let firstname = 'michael';
export let lastname = 'jackson';
export let year = 1958;
//写法2
let firstname = 'michael';
let lastname = 'jackson';
let year = 1958;

export {first,last,year};
export first;// 报错,必须有大括号
//写法3
export function multiplay(x,y){
    return x * y;
}
export class Foo{
    
}
//写法4
function multiplay(x,y){
    return x * y;
}
export {multiplay as mul};//使用as重命名

import关键字

import {firstName, lastName, year} from './profile'; //写法1
import { lastname as surname } from './profile'; //写法2,使用as重命名
import 'lodash'; //写法3,加载并执行

##NPM Node Package Manager的缩写,直译过来就是Node程序包管理器。通过它能使JS程序员轻松地共享和重用代码以及管理他们所共享的代码。

  • 类似工具 JavaScript的bower、centos的yum、php的composer。

  • bower和npm区别 bower主要用于前端,npm主要用于node的后端,对于前端的代码来讲,代码体积的大小是很敏感的事,而node却不关心代码体积多一点少一点。所以,他们俩主要区别为它俩的依赖逻辑不同。

    管理依赖时,npm会传递依赖,而bower不会。例如:bootstrap依赖jquery,我们通过bower声明对bootstrap的依赖,那么最终只会产生对bootstrap的依赖而不会依赖到jquery,而npm会传递整个依赖树。

安装和配置

  • 安装 NPM是随同NodeJS一起安装的包管理工具,进入node官网,选择和你环境匹配的操作系统类型和位数,然后下载nodejs的安装包,下载之后直接安装即可。
  • 配置 如果你的安装是正确的,那么你就应该可以直接使用npm命令了。不过在使用之前最好先做一些配置。
    • 配置prefix npm config set prefix D:\work\Nodejs\node_global
    • 配置cache npm config set cache D:\work\Nodejs\node_cache
    • 配置registry npm config set registry https://registry.npm.taobao.org
    • 配置NPM的全局bin目录,将1配置的prefix对应的路径添加到PATH环境变量(仅windows系统)

常用命令

  • config
    • set 设置变量 npm config set $key $value
    • get 获取变量的值 npm config get $key
    • delete 删除某个变量 npm config delete $key
    • list 获取所有的变量
    • edit 使用文本软件打开配置文件
  • bin npm bin [-g] 获取npm包的bin目录
    • -g 加上这个参数表示获取全局bin目录
  • prefix npm prefix [-g] 获取npm包的目录的前缀
    • -g 加上这个参数表示获取全局的npm包目录前缀
  • root npm root [-g] 获取npm的根目录.
    • -g 加上这个参数表示获取全局目录
  • bugs npm bugs $package 获取软件包的bug列表地址。比如查看jquery的bug列表:npm bugs jquery
  • docs npm docs $package 获取软件包的文档地址。
  • repo npm dos $package 获取软件包的源码库地址
  • help npm dos $command 查看某个命令的帮助
  • init npm init [-f|--force|-y|--yes] 初始化一个项目,会在初始化的过程中提示你填写一些信息。
    • -f --force -y --yes 如果加上前面这些参数表示直接初始化。
  • run-script npm run $command [-args...] 运行package.json上定义的脚本命令。
  • search npm search $keyword 搜索某个软件包。npm search bootstrap
  • install npm install $package [-g] 安装某个软件包
    • -g 加上这个参数表示安装到全局目录
  • uninstall npm uninstall $package [-g] 卸载某个软件包
    • -g 加上这个参数表示卸载全局目录的包
  • start npm start 表示运行定义在package.json上的start命令,这个命令通常会定义如何启动工程
  • stop npm stop 表示运行定义在package.json上的stop命令,这个命令通常会定义如何停止一个工程
  • test npm test 表示运行定义在package.json上的test命令,这个命令通常会定义测试这个工程的代码

NPM的配置文件

npmrc的四个配置级别
  • 项目级别的配置文件 (/xxx/project-x/.npmrc)

  • 用户级别的配置文件 (~/.npmrc)

  • 全局配置文件 ($PREFIX/etc/npmrc)

  • NPM内置的配置文件 ($NPM_HOME/npmrc)

优先级为: 项目级别>用户级别>全局配置>NPM内置

可以通过命令行npm config ls -l查看所有npmrc的默认配置

npmrc的各项配置的文档说明

package.json

package.json是npm的项目的配置文件。通过这个文件我们可以描述项目,定义模块名和版本,定义对第三方库的依赖、用于构建项目的各种命令。

  • name npm的软件包名,要唯一。
  • version 版本号
  • title 软件包的标题
  • description 描述
  • keywords 关键字,我们运行的npm search $keywords实际上就是去匹配description,keywords等字段
  • bugs & homepage & repository & dist & author 软件包的项目信息。
  • files 描述项目的源码文件
  • engines 依赖的node版本
  • optionalDependencies & dependencies & devDependencies 定义这个软件包的依赖。分别为可选依赖,运行依赖,和开发时的依赖。其中运行时的依赖会传递给依赖这个包的项目。
  • scripts 定义构建项目的相关命令(脚本)

####版本表达式 | 表达式 | 版本范围 | | -------- | :----: | | >= 1.2.7 | 大于等于1.2.7 | | >=1.2.7 <1.3.0 | 1.2.7,1.2.8,1.2.9 | | 1.2.3 – 2.3.4 | >=1.2.3 <=2.3.4 | | 1.2 – 2.3.4 | >=1.2.0 <=2.3.4 | | 1.2.3 – 2.3 | >=1.2.3 <2.4.0 | | 1.2.3 – 2 | >=1.2.3 <3.0.0 | | * | >=0.0.0 | | 1.x(等价于1.X) | >=1.0.0 <2.0.0 | | 1.2.x | >=1.2.0 <1.3.0 | | “”(等价于*) | >=0.0.0 | | 1(等价于1.x.x) | >=1.0.0 <2.0.0 | | 1.2(等价于1.2.x) | >=1.2.0 <1.3.0 | | ~1.2.3(>=1.2.3 <1.(2+1).0) | >=1.2.3 <1.3.0 | | ~1.2(>=1.2.0 <1.(2+1).0) | >=1.2.0 <1.3.0 | | ~1(>=1.0.0 <(1+1).0.0) | >=1.0.0 <2.0.0 | | ~0.2.3(>=0.2.3 <0.(2+1).0) | >=0.2.3 <0.3.0 | | ~0.2(>=0.2.0 <0.(2+1).0) | >=0.2.0 <0.3.0 | | ~0(>=0.0.0 <(0+1).0.0) | >=0.0.0 <1.0.0 | | ~1.2.3-beta.2 | >=1.2.3-beta.2 <1.3.0 | | ^1.2.3 | >=1.2.3 <2.0.0 | | ^0.2.3 | >=0.2.3 <0.3.0 | | ^0.0.3 | >=0.0.3 <0.0.4 | | ^1.2.3-beta.2 | >=1.2.3-beta.2 <2.0.0 | | ^0.0.3-beta | >=0.0.3-beta <0.0.4 | | ^1.2.x | >=1.2.0 <2.0.0 | | ^0.0.x | >=0.0.0 <0.1.0 | | ^0.0 | >=0.0.0 <0.1.0 | | ^1.x | >=1.0.0 <2.0.0 | | ^0.x | >=0.0.0 <1.0.0 |

webpack

一个模块化工具,有一些编译、构建和打包的功能,不仅如此,还能自动热加载我们的代码,是的修改代码->得到反馈的时间更短,提升我们的开发效率和体验。

命令行支持

按照惯例,学习一个工具之前先看看它的命令行工具如何使用似乎是一个不错的方法。

  • webpack <entry> [<entry>] <output> 最基本的命令
  • webpack help 查看帮助 通过help命令可以知道webpack的参数大约可以分为一下这么几类
  • 基本参数设置
    • --context 项目的根目录
    • --entry 项目的入口文件
    • --debug 将webpack的loader切换到debug模式
  • 命令行快捷方式
    • -d等价于--debug --devtool eval-cheap-module-source-map --output-pathinfo
    • -p等价于--optimize-minimize --define process.env.NODE_ENV="production"
  • 项目打包输出的参数设置
    • --output-path 打包输出的路径
    • --output-filename 打包输出的文件名
    • --output-source-map-filename source-map的文件名
  • 编译过程的指标统计参数设置
  • 优化编译过程的参数设置
  • 模块的绑定参数设置
  • 模块别名的映射的配置
  • 等等。。

以及还有直接指定配置文件和运行环境的方式

  • --env 指定当前的运行环境(开发环境、生产环境)
  • --config 指定webpack的配置文件

###webpack配置文件

  • entry 项目的入口文件
  • output 项目的输出文件
  • devtool 调试选项的配置,webpack支持8种source-maps的配置。 不过,我测试下来发现chrome浏览器仅支持source-map配置项。其他的调试选项都不支持。
    • eval
    • cheap-eval-source-map
    • cheap-source-map
    • cheap-module-eval-source-map
    • cheap-module-source-map
    • eval-source-map
    • source-map
    • nosources-source-map
  • devServer 用于配置http server的相关信息,比如端口号,是否启用热加载。
  • module 模块化配置,和webpack1.x的loader类似。
  • plugins 配置webpack打包项目的插件。

loaders

webpack将每个文件(.css,.html,.scss,.jpg等)视为一个模块。但是,webpack只能理解JavaScript。loader就是将这些文件转换为模块的组件。

###webpack官方提供的loader

  • style-loader 每一个对css文件的依赖都会在html页面上创建一个style标签,并将css文件的内容插入到这个新增的style标签上。
  • css-loader 读取css文件,并将其转换为纯文本。
  • file-loader 将外部依赖变为一个字符串地址
  • json-loader 解析一个json文件变为一个JS对象
  • less-loader 编译less为css
  • babel-loader 编译ES6、JSX语法为普通的ES5语法

###webpack官方提供的plugins 略。官方文档

babel

babel是一个JavaScript的转译工具,将ES6语法、JSX语法转为es5的实现,提供ES6新增API的JS垫片。

  • 安装

npm install --save-dev babel-cli

  • babel命令行

    babel index.js #输出编译之后的js文本
    babel index.js --out-file index-compiled.js #将index.js的编译内容输出到文件
    babel index.js --out-file index-compiled.js --source-maps  #编译index.js并生成source-map文件
    babel index.js --out-file index-compiled.js --plugins=transform-runtime,transform-es2015-modules-amd  #启用transform-runtime和transform-es2015-modules-amd插件对index.js进行编译
    babel index.js --out-file index-compiled.js --presets=es2015,react #基于预设的插件组对index.js进行编译。
    
    
  • .babelrc babel的编译选项的配置文件。和webpack一样,都是既可以通过命令行又可以通过配置文件配置他们的执行逻辑,配置文件的配置项和命令行几乎一一对应,具体请查看官网文档

plugin

babel的插件比较细粒度,一般是一个插件对应一个语法特性,我们需要编译的js,往往是包含很多新的语法特性,这时候就需要用到preset

preset

preset直译过来就是预设的意思,它表示为一组babel插件的组合设定。。

##react

###create-react-app create-react-app是一个命令行工具,通过执行命令create-react-app projectX就能快速的创建一个标准的react项目,通过它创建的项目内置了一组良好的默认配置。这个工具屏蔽了底层项目配置的复杂性,让新手也能快速的构建和开发react应用,让人摆脱配置的繁琐,更加专注于业务本身。

创建一个新项目,运行命令

create-react-app app 

app项目目录结构

 └─app
    │  package.json
    │  README.md
    │
    ├─public
    │      favicon.ico
    │      index.html
    │      manifest.json
    │
    └─src
            App.css
            App.js
            App.test.js
            index.css
            index.js
            logo.svg
            registerServiceWorker.js

进入项目目录,运行命令

npm start

这时,会启动浏览器并打开项目主页 http://localhost:3000 通过create-react-app创建的项目内置了4个命令,分别是:

  • npm start 启动项目
  • npm test 对项目的代码运行测试用例
  • npm run build 用于构建出生产环境使用的代码
  • npm run eject 如果你对create-react-app这个工具创建出来的项目不满意,你可以通过运行这个命令,拉出被隐藏起来的项目配置文件,扩展和修改他们。不过需要注意的事,这个操作是不可逆的。

支持哪些特性?
  • es6 & jsx & flow
  • Class Fields and Static Properties (es6不支持)
  • source maps
  • autoprefixed css
  • Import CSS and image files directly from JavaScript.
不支持哪些特性?
  • Server rendering.(服务端渲染)
  • 一些实验语法扩展(如装饰器)
  • CSS模块化
  • 直接导入LESS或Sass(但可以通过添加less和sass的依赖使用他们)
  • 组件的热加载

关于less和sass,react认为所有的组件应该是独立的,内聚的,这就意味着css不会被多个组件所共享,有了这个限制,相当于less和sass的最重要的功能都被砍掉了,因此它没有将less和sass集成进来。如果你一定要使用这个功能,其实也是可以用的。

如何启用css预处理工具?
  • 安装node-sass npm-run-all,运行命令
    npm install node-sass npm-run-all -D       #1
    
  • 修改package.json配置文件。
    "scripts": {
    +    "build-css": "node-sass-chokidar src/ -o src/",
    +    "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
    -    "start": "react-scripts start",
    -    "build": "react-scripts build",
    +    "start-js": "react-scripts start",
    +    "start": "npm-run-all -p watch-css start-js",
    +    "build": "npm run build-css && react-scripts build",
         "test": "react-scripts test --env=jsdom",
         "eject": "react-scripts eject"
    }
    

React Storybook

一个所见即所得的工具,通过它你无需启动服务就能和应用直接交互。

Storybook

安装

npm install -g getstorybook

运行

getstorybook

###react-js

jsx
  • 基本语法 遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;遇到代码块(以 { 开头),就用 JavaScript 规则解析。

    <script type="text/babel">
      ReactDOM.render(
        <h1>Hello, world!</h1>,
        document.getElementById('example')
      );
    </script>
    
  • 插入变量、循环 在html标签中通过{name}的方式插入变量,循环需要配合数组的map方法。

    var names = ['Alice', 'Emily', 'Kate'];
    ReactDOM.render(
        <div>
            {
            names.map(function (name) {
              return <div>Hello, {name}!</div>
            })
            }
        </div>,
        document.getElementById('example')
    );
    

React.Component
  • 基本用法,自定义一个组件继承自Component

    import React, { Component } from 'react';
    import logo from './logo.svg';
    import './App.css';
    
    class App extends Component {
      render() {
        return (
          <div className="App">
            <div className="App-header">
              <img src={logo} className="App-logo" alt="logo" />
              <h2>Welcome to React</h2>
            </div>
            <p className="App-intro">
              To get started, edit <code>src/App.js</code> and save to reload.
            </p>
          </div>
        );
      }
    }
    
    export default App;
    
    

注意: 组件类的第一个字母必须大写,否则会报错,比如App不能写成app。另外,组件类只能包含一个顶层标签,否则也会报错。

  • state 与 props state封装了组件的转换规则,枚举出可能的状态,在枚举状态之前需要确定状态种类,不同的状态呈现出不同的行为或者视图,让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

    props是组件的数据层,他们的生命周期和组件,组件一旦被实例化,他们便不会在发生任何变化。

    从表象上来看,state表示那些会变更的数据,而props表示那些不变的数据。

      var LikeButton = React.createClass({
    	  getInitialState: function() {
    		return {liked: false};
    	  },
    	  handleClick: function(event) {
    		this.setState({liked: !this.state.liked});
    	  },
    	  render: function() {
    		var text = this.state.liked ? 'like' : 'unlike';
    		return (
    			<div>
    				<p>{this.props.hint}</p>
    				<button onClick={this.handleClick}>{text}</button>
    			</div>
    		);
    	  }
    	});
    
    	ReactDOM.render(
    	  <LikeButton hint="请点击下面的按钮" />,
    	  document.getElementById('example')
    	);
    
  • propTypes 用来定义组件的props字段的验证规则

    var MyTitle = React.createClass({
      propTypes: {
        title: React.PropTypes.string.isRequired,
      },
    
      render: function() {
         return <h1> {this.props.title} </h1>;
       }
    });
    var data = 123;
    
    ReactDOM.render(
      <MyTitle title={data} />,
      document.body
    );
    
  • defaultProps 表示组件的props默认值

    var MyTitle = React.createClass({
      getDefaultProps : function () {
        return {
          title : 'Hello World'
        };
      },
    
      render: function() {
         return <h1> {this.props.title} </h1>;
       }
    });
    
    ReactDOM.render(
      <MyTitle />,
      document.body
    );
    
  • 事件 见state 与 props提供的代码

  • refs

    var MyComponent = React.createClass({
      handleClick: function() {
        this.refs.myTextInput.focus();
      },
      render: function() {
        return (
          <div>
            <input type="text" ref="myTextInput" />
            <input type="button" value="Focus the text input" onClick={this.handleClick} />
          </div>
        );
      }
    });
    ReactDOM.render(
      <MyComponent />,
      document.getElementById('example')
    );
    
  • 生命周期和方法 组件的生命周期分成三个状态:

  • Mounting:已插入真实 DOM
  • Updating:正在被重新渲染
  • Unmounting:已移出真实 DOM

React 为每个状态都提供了两种处理函数,will 函数在进入状态之前调用,did 函数在进入状态之后调用,三种状态共计五种处理函数。

  • componentWillMount() >- componentDidMount() >- componentWillUpdate(object nextProps, object nextState) >- componentDidUpdate(object prevProps, object prevState) >- componentWillUnmount()

此外,React 还提供两种特殊状态的处理函数。

  • componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用 >- shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用

示例代码

var Hello = React.createClass({
        getInitialState: function () {
          return {
            opacity: 1.0
          };
        },
        componentDidMount: function () {
          this.timer = setInterval(function () {
            var opacity = this.state.opacity;
            opacity -= .05;
            if (opacity < 0.1) {
              opacity = 1.0;
            }
            this.setState({
              opacity: opacity
            });
          }.bind(this), 100);
        },
        render: function () {
          return (
            <div style={{opacity: this.state.opacity}}>
              Hello {this.props.name}
            </div>
          );
        }
      });
      ReactDOM.render(
        <Hello name="world"/>,
        document.getElementById('example')
      );
  • this.props.children 它表示对象的子节点,它的值有三种可能:
    • 当前组件没有子节点 数据类型是undefined;
    • 如果有一个子节点,数据类型是 object;
    • 如果有多个子节点,数据类型就是 array

参考链接


  1. JS标准库
  2. W3school ECMAScript
  3. 阮一峰-ECMAScript 6 入门
  4. NPM 官方文档
  5. Less 中文站
  6. 夕阳白雪-Node.js模块依赖及版本号
  7. Webpack 官网
  8. 入门Webpack,看这篇就够了
  9. Babel官网
  10. 阮一峰-React入门实例教程
  11. React官方文档

转载于:https://my.oschina.net/u/90398/blog/916872

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值