react学习笔记2

export/import导出/导入模块

模块功能主要由两个命令构成:exportimportexport命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

ES6模块不是对象,而是通过export命令显式指定输出的代码,输入时也采用静态命令的形式。

// ES6模块

import { stat, exists, readFile } from  'fs';

上面代码的实质是从fs模块加载3个方法,其他方法不加载。这种加载称为“编译时加载”,即ES6可以在编译时就完成模块加载,效率要比CommonJS模块的加载方式高。当然,这也导致了没法引用ES6模块本身,因为它不是对象。

由于ES6模块是编译时加载,使得静态分析成为可能。有了它,就能进一步拓宽JavaScript的语法,比如引入宏(macro)和类型检验(type system)这些只能靠静态分析实现的功能。

除了静态加载带来的各种好处,ES6模块还有以下好处。

  • 不再需要UMD模块格式了,将来服务器和浏览器都会支持ES6模块格式。目前,通过各种工具库,其实已经做到了这一点。

  • 将来浏览器的新API就能用模块格式提供,不再必要做成全局变量或者navigator对象的属性。

  • 不再需要对象作为命名空间(比如Math对象),未来这些功能可以通过模块提供。

默认情况下,JavaScript中在模块内的所有声明都是本地的,外部无法访问。如果需要公开模块中部分声明的内容,并让其它模块加以使用,这个时候就需要导出功能,最简单的方式是添加export关键字导出模块。

可以导出的内容包括类、函数以及var、let和const修饰的变量。export命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错,import命令也是如此。

使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。

import命令具有提升效果,会提升到整个模块的头部,首先执行。由于import是静态执行,所以不能使用表达式和变量,这些只有在运行时才能得到结果的语法结构。

import后面的from指定模块文件的位置,可以是相对路径,也可以是绝对路径,.js路径可以省略。如果只是模块名,不带有路径,那么必须有配置文件,告诉 JavaScript 引擎该模块的位置

导入单个导出

给定一个名为myExport的对象或值,它已经从模块my-module导出(因为整个模块被导出)或显式地导出(使用export语句),将myExport插入当前作用域。

import  {myExport}  from  '/modules/my-module.js';

导入多个导出

这将foo和bar插入当前作用域。

import  {foo, bar}  from  '/modules/my-module.js';

export default 和 export 区别:

1.export与export default均可用于导出常量、函数、文件、模块等
2.你可以在其它文件或模块中通过import+(常量 | 函数 | 文件 | 模块)名的方式,将其导入,以便能够对其进行使用
3.在一个文件或模块中,export、import可以有多个,export default仅有一个
4.通过export方式导出,在导入时要加{ },export default则不需要

严格模式

ES6的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";

严格模式主要有以下限制。

-变量必须声明后再使用

  • 函数的参数不能有同名属性,否则报错

  • 不能使用with语句

  • 不能对只读属性赋值,否则报错

  • 不能使用前缀0表示八进制数,否则报错

  • 不能删除不可删除的属性,否则报错

  • 不能删除变量delete prop,会报错,只能删除属性delete global[prop]

  • eval不会在它的外层作用域引入变量

  • evalarguments不能被重新赋值

  • arguments不会自动反映函数参数的变化

  • 不能使用arguments.callee

  • 不能使用arguments.caller

  • 禁止this指向全局对象

  • 不能使用fn.callerfn.arguments获取函数调用的堆栈

  • 增加了保留字(比如protectedstaticinterface

Components and Props

参考资料:https://reactjs.org/docs/components-and-props.html

function formatDate(date) {

 return date.toLocaleDateString();

}

function Avatar(props) {

 return (

 <img

 className="Avatar"

 src={props.user.avatarUrl}

 alt={props.user.name}

 />

 );

}

function UserInfo(props) {

 return (

 <div className="UserInfo">

 <Avatar user={props.user} />

 <div className="UserInfo-name">{props.user.name}</div>

 </div>

 );

}

function Comment(props) {

 return (

 <div className="Comment">

 <UserInfo user={props.author} />

 <div className="Comment-text">{props.text}</div>

 <div className="Comment-date">

 {formatDate(props.date)}

 </div>

 </div>

 );

}

const comment = {

 date: new Date(),

 text: 'I hope you enjoy learning React!',

 author: {

 name: 'Hello Kitty',

 avatarUrl: 'http://placekitten.com/g/64/64',

 },

};

ReactDOM.render(

 <Comment

 date={comment.date}

 text={comment.text}

 author={comment.author}

 />,

 document.getElementById('root')

);

前面三段较为冗余的写法:

function Comment(props) {

 return (

 <div className="Comment">

 <div className="UserInfo">

 <img

 className="Avatar"

 src={props.author.avatarUrl}

 alt={props.author.name}

 />

 <div className="UserInfo-name">

 {props.author.name}

 </div>

 </div>

 <div className="Comment-text">{props.text}</div>

 <div className="Comment-date">

 {formatDate(props.date)}

 </div>

 </div>

 );

}

页面效果:


image.png

Hello Kitty

I hope you enjoy learning React!

6/4/2018

React Props

state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据。

Classes

constructor

构造函数**constructor **是用于创建和初始化类中创建的一个对象的一种特殊方法。

语法

constructor([arguments]) { ... }

描述

  • 在一个类中只能有一个名为 “constructor” 的特殊方法。 一个类中出现多次构造函数 (constructor)方法将会抛出一个 SyntaxError 错误。
  • 在一个构造方法中可以使用super关键字来调用一个父类的构造方法。
  • 如果没有显式指定构造方法,则会添加默认的 constructor 方法。
  • 如果不指定一个构造函数(constructor)方法, 则使用一个默认的构造函数(constructor)。

ES5的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。ES6的继承机制完全不同,实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this。

如果子类没有定义constructor方法,这个方法会被默认添加,代码如下。也就是说,不管有没有显式定义,任何一个子类都有constructor方法。

constructor(...args) {

  super(...args);

}

另一个需要注意的地方是,在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建,是基于对父类实例加工,只有super方法才能返回父类实例。

extends

**extends**关键字用于类声明或者类表达式中,以创建一个类,该类是另一个类的子类。

语法

class ChildClass extends ParentClass { ... }

描述

extends关键字用来创建一个普通类或者内建对象的子类。

继承的.prototype必须是一个Object 或者 null

类的prototype属性和proto属性

大多数浏览器的ES5实现之中,每一个对象都有__proto__属性,指向对应的构造函数的prototype属性。Class作为构造函数的语法糖,同时有prototype属性和__proto__属性,因此同时存在两条继承链。

(1)子类的proto属性,表示构造函数的继承,总是指向父类。
(2)子类prototype属性的proto属性,表示方法的继承,总是指向父类的prototype属性。

class  A {

}

class  B  extends  A {

}

B.__proto__ === A // true

B.prototype.__proto__ === A.prototype // true

上面代码中,子类B的proto属性指向父类A,子类B的prototype属性的proto属性指向父类A的prototype属性。

这两条继承链,可以这样理解:作为一个对象,子类(B)的原型(proto属性)是父类(A);作为一个构造函数,子类(B)的原型(prototype属性)是父类的实例。

B.prototype = new A();

// 等同于

B.prototype.__proto__ = A.prototype;

static

static关键字为一个类定义了一个静态方法

类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。

为什么要保存至PACKAGE.JSON?

因为node插件包非常大,版本庞杂,所以不加入package信息,模块间的依赖变得非常困难,将配置信息写入package.json并将其加入版本管理,其他开发者对应下载即可(命令提示符执行npm install,则会根据package.json下载所有需要的包)。 每个项目的根目录下面,一般都有一个package.json文件,定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等元数据)。npm install 命令根据这个配置文件,自动下载所需的模块,也就是配置项目所需的运行和开发环境。

PACKAGE.JSON 属性说明:

  • name - 包名。(不要把node或者js放在名字中)
  • version - 包的版本号。
  • dependencies - 项目运行所依赖的模块
  • devDependencies - 项目开发所需要的模块
  • bin - 这需要在你的package.json中提供一个bin字段,它是一个命令名和本地文件名的映射。在安装时,如果是全局安装,npm将会使用符号链接把这些文件链接到prefix/bin,如果是本地安装,会链接到./node_modules/.bin/

使用npm卸载插件:npm uninstall < name > [-g] [--save-dev] PS:不要直接删除本地插件包

查看当前目录已安装插件:npm list

CNPM介绍:

官方网址:http://npm.taobao.org

安装:命令提示符执行npm install cnpm -g --registry=https://registry.npm.taobao.org

注意:安装完后最好查看其版本号cnpm -v或关闭命令提示符重新打开,安装完直接使用有可能会出现错误

Q:全局安装和本地安装的区别?

A:因为全局模式安装,包可以供所有的程序使用。本地安装则不可以。 npm 默认会把包安装到当前目录下。这反映了 npm 不同的设计哲学。如 果把包安装到全局,可以提高程序的重复利用程度,避免同样的内容的多 份副本,但坏处是难以处理不同的版本依赖。如果把包安装到当前目录, 或者说本地,则不会有不同程序依赖不同版本的包的冲突问题,同时还减 轻了包作者的 API 兼容性压力,但缺陷则是同一个包可能会被安装许多次。

Q:为什么进行了全局安装还要进行本地安装

1、在js实例代码中,默认下node.js会在NODE_PATH和目前js所在项目下的node_modules文件夹下去寻找模块,因此,如果只是全局安装,不能直接通过require()的方式去引用模块,需要手动解决包路径的配置问题,当然你也可以复制全局安装的node_modules文件夹到项目下,还有办法可以选择将环境变量的NODE_PATH设置为C:\Program Files\nodejs。

2.对于包的更新不好管理,可能你需要为每个包重新命名,如gulp@3.8.1、gulp@3.9.1...,为了区别不同项目使用指定的包,保证模块之间的相互依赖,区别每个项目正常运行

Q:如何在package.JSON的dependencies和devDependencies写入信息

npm install --save babel-cli和npm install -dev babel-cli使用这两个命令安装后可自动写入文件

npm install --save-dev babel-cli也可以在一起用

参考文献:https://www.jianshu.com/p/f581cf9360a2

React Demo

class Square extends React.Component {

 render() {

 return (

 <button className="square">

 {this.props.value}

 </button>

 );

 }

}

class Board extends React.Component {

 renderSquare(i) {

 return <Square value={i}/>;

 }

 render() {

 const status = 'Next player: X';

 return (

 <div>

 <div className="status">{status}</div>

 <div className="board-row">

 {this.renderSquare(0)}

 {this.renderSquare(1)}

 {this.renderSquare(2)}

 </div>

  <div className="board-row">

 {this.renderSquare(3)}

 {this.renderSquare(4)}

 {this.renderSquare(5)}

 </div>

 <div className="board-row">

 {this.renderSquare(6)}

 {this.renderSquare(7)}

 {this.renderSquare(8)}

 </div>

 </div>

 );

 }

}

class Game extends React.Component {

 render() {

 return (

 <div className="game">

 <div className="game-board">

 <Board />

 </div>

 <div className="game-info">

 <div>{/* status */}</div>

 <ol>{/* TODO */}</ol>

 </div>

 </div>

 );

 }

}

// ========================================

ReactDOM.render(

 <Game />,

 document.getElementById('root')

);

Next player: X

012

345

678

参考文献:https://reactjs.org/tutorial/tutorial.html

常用代码注释

改进1:setState

上面的代码改成这样:

class Square extends React.Component {

  **constructor(props) {**

 **super(props);**

 **this.state = {**

 **value: null,**

 **};**

 **}**

 render() {

 return (

 <button className="square" **onClick={() => this.setState({value: 'X'})**}>

 {this.state.value}

 </button>

 );

 }

}

每当 this.setState 被调用时,都会计划对组件的更新,导致 React 合并传递的 state(状态) ,更新和渲染组件及其子组件。 当组件渲染完成时,this.state.value 的值将是 'X' ,所以你会在网格中看到一个 X 。

如果您点击任何方格,它里面应该会出现一个 X 。

State(状态) 提升

当重构 React 组件时,提升 state(状态) 是非常常见的. 当您要聚合来自多个子节点的数据 或 使两个子组件之间相互通信时,提升 state(状态) ,使其存储在父组件中。父组件可以通过 props(属性) 把 state(状态) 传递回子组件,以使子组件始终与父组件同步。

由于组件的 state(状态) 被认为是私有的,我们不能从 Square(方格) 组件直接更新 Board(棋盘) 的 state(状态) 。

通常的模式是将一个函数从 Board(棋盘) 组件 传递到 Square(方格) 组件上,该函数在方格被点击时调用。 再次修改 Board(棋盘) 组件中 renderSquare ,修改为:

renderSquare(i) {

  return (

  <Square

  value={this.state.squares[i]}

  onClick={() =>  this.handleClick(i)}

  />

 );

 }

我们把 Board(棋盘) 组件中 2 个props(属性) 传递给 Square(方格) 组件:value 和 onClick。后者是一个函数,Square(方格) 组件 可以调用该函数。

遇到的问题

1.’create-react-app' is not recognized as an internal or external command.

是环境变量问题。需要增加npm的环境变量路径。

C:\Users\e******\AppData\Roaming\npm;

2. React 中的 registerServiceWorker是干什么的?

用于在生产环境中为用户在本地创建一个service worker 来缓存资源到本地,提升应用的访问速度.

service worker是在后台运行的一个线程,可以用来处理离线缓存、消息推送、后台自动更新等任务。registerServiceWorker就是为react项目注册了一个service worker,用来做资源的缓存,这样你下次访问时,就可以更快的获取资源。而且因为资源被缓存,所以即使在离线的情况下也可以访问应用(此时使用的资源是之前缓存的资源)。注意,registerServiceWorker注册的service worker 只在生产环境中生效(process.env.NODE_ENV === 'production')

常用命令

打开命令行 win+R cmd

打开环境变量:start-〉自己的图标-〉Change 没有environment variables-〉上面的path。

查找环境变量path路径:echo %PATH%

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容