1.All the fundamental React.js concepts, jammed into this single Medium article
這篇簡單Medium文章包含了所有基本的react.js概念(下面程式碼都摘自原文 詳細瞭解請閱讀原文)
基本概念#1:React就是元件 (React is all about components)
React是圍繞可複用元件(resuable components)的概念設計的。你可以定義小元件然後組合成更大的元件。即使在不同專案中,所有大型或者小型的元件都可以重複使用。一個react元件-最簡單的形式-就是一個簡單javaScript函式(a plain-old javaScript function)
// 例子 1
// https://jscomplete.com/repl?j=Sy3QAdKHW
function Button (props){
//如:return 一個 dom 元素
return <button type ="submit">{props.lable}</button>
}
//將Button元件在瀏覽器中渲染
ReactDOM.render(<Button label = "save" />, mountNode)
複製程式碼
請注意下面關於例子1:
- 元件的名字要以大寫字母開頭。這一要求是為了在混合使用HTML元素跟React元素時,區分它們。
- 每一個元件可以有屬性列表,就像跟HTML元素一樣。在react中,這個列表的名字稱為props。
- 我們看到上面Button元件的返回輸出值看起來像HTML的形式。它既不javaSCript也不是HTML,甚至不是react.js。但是,它很受歡迎,成為了react應用程式的預設設定。它叫做JSX,是javascript的擴充套件。
基本概念#2:JSX的變化是什麼(What the flux is JSX)
下面是例子1不用JSX語法:
// 例子 2 -
// https://jscomplete.com/repl?j=HyiEwoYB-
function Button (props) {
return React.createElement(
"button",
{ type: "submit" },
props.label
);
}
//
ReactDOM.render(
React.createElement(Button, { label: "Save" }),
mountNode
);
複製程式碼
createElement是react 中的API,creactElement 實際上就是建立樹
// 例子 3
// https://jscomplete.com/repl?j=r1GNoiFBb
const InputForm = React.createElement(
"form",
{ target: "_blank", action: "https://google.com/search" },
React.createElement("div", null, "Enter input and click Search"),
React.createElement("input", { name: "q", className: "input" }),
React.createElement(Button, { label: "Search" })
);
// InputForm
function Button (props) {
return React.createElement(
"button",
{ type: "submit" },
props.label
);
}
//
ReactDOM.render(InputForm, mountNode);
複製程式碼
請注意以下幾點:
InputForm
不是react元件,它是react元素。這是為什麼我們在ReactDOM.render
的時候直接使用,而沒有使用<InputForm />
形式React.createElement
函式在第一第二引數之後接受多個引數。 從第三個開始引數列表是包含建立子元素的- 當元素不需要任何屬性或者props的時候,
React.createElement
的第二個引數可以是null 或者空物件 - 我們可以將HTML元素和React元素混合使用
- React API 嘗試儘可能的接近DOM API
我們習慣看或者寫HTML形式,所以採用接近HTML的語法形式 JSX
// 例子 4 - JSX (跟例3 比較)
// https://jscomplete.com/repl?j=SJWy3otHW
const InputForm =
<form target="_blank" action="https://google.com/search">
<div>Enter input and click Search</div>
<input name="q" className="input" />
<Button label="Search" />
</form>;
function Button (props) {
// Returns a DOM element here. For example:
return <button type="submit">{props.label}</button>;
}
//
ReactDOM.render(InputForm, mountNode);
複製程式碼
請注意以下幾點:
- 這不是HTML,比如這裡是用
className
代替class
- 考慮將上面看似HTML的形式看作javascript,可以看到在最後新增了分號
上面寫的例4形式是JSX,而瀏覽器看到的相當於它的編譯版本例3。所以,我們需要前處理器(pre-processor)將就JSX版本的轉換成React.createElement
順便說一句,JSX可以單獨使用,它不是 React-only
基本概念#3:可以在JSX中任何地方使用javaScipt表示式
在JSX中,你可以使用任何javaScript表示式,用一對花括號(curly braces)包圍
// 例5
// https://jscomplete.com/repl?j=SkNN3oYSW
const RandomValue = () =>
<div>
{ Math.floor(Math.random() * 100) }
</div>;
//
ReactDOM.render(<RandomValue />, mountNode);
複製程式碼
在花括號內,寫入任何javaScript表示式,這種形式類似於 javaScript的模板語法${}
JSX 的唯一約束就是: 只能是表示式。因此,我們不能使用常規的if語句,需要使用三目表示式(ternary expression)
javaScript 變數(variable)也是表示式(expression),所以元件接收的props ,需要放在 花括號中
javaScript 物件也是表示式。有時我們在花括號內使用javaScript物件,這使它看起來像花括號,但其實它是花括號內寫入的物件。一個例子就是在React中我們將CSS樣式物件傳遞給style屬性
// 列6
// https://jscomplete.com/repl?j=S1Kw2sFHb
const ErrorDisplay = ({message}) =>
<div style={ { color: 'red', backgroundColor: 'yellow' } }>
{message}
</div>;
ReactDOM.render(
<ErrorDisplay
message="These aren't the droids you're looking for"
/>,
mountNode
);
複製程式碼
在jSX也可以使用React元素,因為這個它也是一個表達。請記住React元素本質上是函式呼叫
// 例7 - 在 {}使用 react元素
// https://jscomplete.com/repl?j=SkTLpjYr-
const MaybeError = ({errorMessage}) =>
<div>
{errorMessage && <ErrorDisplay message={errorMessage} />}
</div>;
const ErrorDisplay = ({message}) =>
<div style={ { color: 'red', backgroundColor: 'yellow' } }>
{message}
</div>;
ReactDOM.render(
<MaybeError
errorMessage={Math.random() > 0.5 ? 'Not good' : ''}
/>,
mountNode
);
複製程式碼
你也可以在JSX中使用javaScript的集合(collection)方法(map
,reduce
,filter
,concat
,等等),因為它們返回的也是表示式
// 例8- 在 {}使用 陣列map
// https://jscomplete.com/repl?j=SJ29aiYH-
const Doubler = ({value=[1, 2, 3]}) =>
<div>
{value.map(e => e * 2)}
</div>;
ReactDOM.render(<Doubler />, mountNode);
複製程式碼
基本概念#4:你可以用class 來寫React 元件
// Example 9 - 使用class寫react元件
// https://jscomplete.com/repl?j=ryjk0iKHb
class Button extends React.Component {
render() {
return <button>{this.props.label}</button>;
}
}
ReactDOM.render(<Button label="Save" />, mountNode);
複製程式碼
// 例 10 -
// https://jscomplete.com/repl?j=rko7RsKS-
class Button extends React.Component {
constructor(props) {
super(props);
this.id = Date.now();
}
render() {
return <button id={this.id}>{this.props.label}</button>;
}
}
ReactDOM.render(<Button label="Save" />, mountNode);
複製程式碼
// 例 11
// https://jscomplete.com/repl?j=H1YDCoFSb
class Button extends React.Component {
clickCounter = 0;
handleClick = () => {
console.log(`Clicked: ${++this.clickCounter}`);
};
render() {
return (
<button id={this.id} onClick={this.handleClick}>
{this.props.label}
</button>
);
}
}
// Use it
ReactDOM.render(<Button label="Save" />, mountNode);
複製程式碼
基本概念#5:React事件:兩個重要的差異
// 例 12
// https://jscomplete.com/repl?j=HkIhRoKBb
class Form extends React.Component {
handleSubmit = (event) => {
event.preventDefault();
console.log('Form submitted');
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<button type="submit">Submit</button>
</form>
);
}
}
ReactDOM.render(<Form />, mountNode);
複製程式碼
基本概念#6: ( Every React component has a story)
基本概念#7: React元件有私有狀態
// 例子 13 -
// https://jscomplete.com/repl?j=H1fek2KH-
class CounterButton extends React.Component {
state = {
clickCounter: 0,
currentTimestamp: new Date(),
};
handleClick = () => {
this.setState((prevState) => {
return { clickCounter: prevState.clickCounter + 1 };
});
};
componentDidMount() {
setInterval(() => {
this.setState({ currentTimestamp: new Date() })
}, 1000);
}
render() {
return (
<div>
<button onClick={this.handleClick}>Click</button>
<p>Clicked: {this.state.clickCounter}</p>
<p>Time: {this.state.currentTimestamp.toLocaleString()}</p>
</div>
);
}
}
ReactDOM.render(<CounterButton />, mountNode);
複製程式碼