react學習筆記2
export/import匯出/匯入模組
模組功能主要由兩個命令構成:export
和import
。export
命令用於規定模組的對外介面,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
不會在它的外層作用域引入變數eval
和arguments
不能被重新賦值arguments
不會自動反映函式引數的變化不能使用
arguments.callee
不能使用
arguments.caller
禁止
this
指向全域性物件不能使用
fn.caller
和fn.arguments
獲取函式呼叫的堆疊增加了保留字(比如
protected
、static
和interface
)
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>
);
}
頁面效果:
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介紹:
安裝:命令提示符執行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%
相關文章
- react 學習筆記React筆記
- react學習筆記React筆記
- React 學習筆記【三】React筆記
- React 學習筆記【一】React筆記
- React 學習筆記【二】React筆記
- React學習筆記-元件React筆記元件
- React學習筆記-JSXReact筆記JS
- React學習筆記1—起步React筆記
- react小書學習筆記React筆記
- React Hooks的學習筆記ReactHook筆記
- react native學習筆記(三)React Native筆記
- react native學習筆記(二)React Native筆記
- react native學習筆記(一)React Native筆記
- React學習筆記-列表 & KeysReact筆記
- React Native框架探索學習筆記React Native框架筆記
- React Native Android學習筆記 - 2015React NativeAndroid筆記
- React生命週期學習筆記React筆記
- React入門指南(學習筆記)React筆記
- React學習筆記-事件處理React筆記事件
- React學習筆記-條件渲染React筆記
- React學習筆記-State(狀態)React筆記
- Vue學習筆記2Vue筆記
- 學習筆記2(下)筆記
- RocketMQ學習筆記 2MQ筆記
- Python學習筆記(2)Python筆記
- Solidity學習筆記-2Solid筆記
- vue學習筆記-2Vue筆記
- hibernate學習筆記(2)筆記
- MySQL學習筆記2MySql筆記
- React筆記:React基礎(2)React筆記
- React學習筆記知識點整理React筆記
- <react學習筆記(2)>JSX語法和樣式的設定React筆記JS
- koa2學習筆記筆記
- 2-SAT 學習筆記筆記
- Grub2 學習筆記筆記
- <react學習筆記(1)>認識react和環境搭建React筆記
- React學習手冊-React執行機制筆記(二)React筆記
- 強化學習-學習筆記2 | 價值學習強化學習筆記