React:創(chuàng)建一個簡單的 JSX 元素
React 是由 Facebook 創(chuàng)建和維護的開源視圖庫玻墅。它是渲染當代 Web 應(yīng)用程序用戶界面(UI)的絕佳工具意述。
React 使用名為 JSX 的 JavaScript 語法擴展凑懂,允許你直接在 JavaScript 中編寫 HTML。這有幾個好處念逞。它允許你在 HTML 中使用 JavaScript 的完整程序功能枚荣,并有助于保持代碼的可讀性碗脊。
但是,由于瀏覽器不能解析 JSX橄妆,因此必須將 JSX 代碼編譯為 JavaScript望薄。比如 轉(zhuǎn)換器 Babel 。
ReactDOM.render(JSX, document.getElementById('root'))
這個函數(shù)調(diào)用是將你的 JSX 置于 React 自己的輕量級 DOM 中呼畸。然后痕支,React 使用自己的 DOM 快照來優(yōu)化更新實際 DOM 的特定部分。
React:創(chuàng)建一個復(fù)雜的 JSX 元素
// 幾個作為兄弟元素而編寫的JSX元素沒有父元素包裹將不會被轉(zhuǎn)換
// 有效的 JSX:
<div>
<p>Paragraph One</p>
<p>Paragraph Two</p>
<p>Paragraph Three</p>
</div>
const JSX = (
<div>
<h1>Heading.</h1>
<p>Paragraph</p>
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</div>
);
React:在 JSX 中添加注釋
要將注釋放在 JSX 中蛮原,可以使用{/* */}
語法來包裹注釋文本卧须。
React:渲染 HTML 元素為 DOM 樹
在 React 中,我們可以使用它的的渲染 API(ReactDOM)將此 JSX 直接渲染到 HTML DOM儒陨。
ReactDOM 提供了一個簡單的方法來將 React 元素呈現(xiàn)給 DOM花嘶,如下所示:ReactDOM.render(componentToRender, targetNode)
,其中第一個參數(shù)是要渲染的 React 元素或組件蹦漠,第二個參數(shù)是要將組件渲染到的 DOM 節(jié)點椭员。
React:在 JSX 中定義一個 HTML Class
JSX 的一個關(guān)鍵區(qū)別是你不能再使用class
這個單詞來定義 HTML 的 class 名。這是因為class
是 JavaScript 中的關(guān)鍵字笛园。JSX 使用className
代替隘击。
事實上,JSX 中所有 HTML 屬性和事件引用的命名約定都變成了駝峰式
研铆。
React:了解自動閉合的 JSX 標記
JSX 不同于 HTML 的另一個重要方面是自閉合標簽埋同。
任何 JSX 元素都可以使用自閉合標簽編寫,并且每個元素都必須關(guān)閉棵红。例如凶赁,換行標簽必須始終編寫為<br />
。另一方面<div>
可以寫成<div />
或者<div></div>
。
const JSX = (
<div>
<h2>Welcome to React!</h2> <br />
<p>Be sure to close all tags!</p>
<hr />
</div>
);
React:創(chuàng)建一個無狀態(tài)的函數(shù)組件
組件是 React 的核心虱肄。
有兩種方法可以創(chuàng)建 React 組件致板。第一種方法是使用 JavaScript 函數(shù)。以這種方式定義組件會創(chuàng)建無狀態(tài)功能組件
咏窿。目前斟或,可以將無狀態(tài)組件視為可以接收數(shù)據(jù)并對其進行渲染的組件,但是它不管理或跟蹤對數(shù)據(jù)的更改翰灾。
要用函數(shù)創(chuàng)建組件,只需編寫一個返回 JSX 或null
的 JavaScript 函數(shù)稚茅。需要注意的一點是纸淮,React 要求你的函數(shù)名以大寫字母開頭。
const DemoComponent = function() {
return (
<div className='customClass' />
);
};
React:創(chuàng)建一個 React 組件
定義 React 組件的另一種方法是使用 ES6 的class
語法亚享。
class Kitten extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<h1>Hi</h1>
);
}
}
React:用組合的方式創(chuàng)建一個 React 組件
const ChildComponent = () => {
return (
<div>
<p>I am the child</p>
</div>
);
};
class ParentComponent extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h1>I am the parent</h1>
<ChildComponent />
</div>
);
}
};
React:使用 React 渲染嵌套組件
const TypesOfFruit = () => {
return (
<div>
<h2>Fruits:</h2>
<ul>
<li>Apples</li>
<li>Blueberries</li>
<li>Strawberries</li>
<li>Bananas</li>
</ul>
</div>
);
};
const Fruits = () => {
return (
<div>
<TypesOfFruit />
</div>
);
};
class TypesOfFood extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h1>Types of Food:</h1>
<Fruits />
</div>
);
}
};
React:組合 React 組件
class Fruits extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h2>Fruits:</h2>
<NonCitrus />
<Citrus />
</div>
);
}
};
class TypesOfFood extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h1>Types of Food:</h1>
<Fruits />
<Vegetables />
</div>
);
}
};
React:渲染 class 組件為 Dom 樹
React 組件傳遞到ReactDOM.render()
與 JSX 元素略有不同咽块。對于 JSX 元素,你傳入的是要渲染的元素的名稱欺税。但是侈沪,對于 React 組件,你需要使用與渲染嵌套組件相同的語法晚凿,例如ReactDOM.render(<ComponentToRender />, targetNode)
亭罪。
class TypesOfFood extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h1>Types of Food:</h1>
<Fruits />
<Vegetables />
</div>
);
}
};
ReactDOM.render(<TypesOfFood />, document.getElementById("challenge-node"));
React:從零開始寫一個 React 組件
class MyComponent extends React.Component {
constructor(props){
super(props)
}
render(){
return (
<div>
<h1>My First React Component!</h1>
</div>
)
}
}
ReactDOM.render(<MyComponent />, document.getElementById("challenge-node"))
React:將 Props 傳遞給無狀態(tài)函數(shù)組件
假設(shè)你有一個App
組件,該組件渲染了一個名為Welcome
的子組件歼秽,它是一個無狀態(tài)函數(shù)組件应役。你可以通過以下方式給Welcome
傳遞一個user屬性:
<App>
<Welcome user='Mark' />
</App>
使用自定義 HTML 屬性,React 支持將屬性user
傳遞給組件Welcome
燥筷。由于Welcome
是一個無狀態(tài)函數(shù)組件箩祥,它可以像這樣訪問該值:
const Welcome = (props) => <h1>Hello, {props.user}!</h1>
自定義屬性中使用 javascript 需要使用花括號,并且不需要引號肆氓。
const CurrentDate = (props) => {
return (
<div>
<p>The current date is: { props.date } </p>
</div>
);
};
class Calendar extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h3>What date is it?</h3>
<CurrentDate date={Date()} />
</div>
);
}
};
React:傳遞一個數(shù)組作為 Props
要將數(shù)組傳遞給 JSX 元素袍祖,必須將其視為 JavaScript 并用花括號括起來。
<ParentComponent>
<ChildComponent colors={["green", "blue", "red"]} />
</ParentComponent>
const ChildComponent = (props) => <p>{props.colors.join(', ')}</p>
React:使用默認的 Props
React 還有一個設(shè)置默認 props 的選項谢揪。如果你聲明MyComponent.defaultProps = { location: 'San Francisco' }
蕉陋,即定義一個 location 屬性,并且其值在沒有另行制定的情況下被設(shè)置為字符串San Francisco拨扶。如果 props 未定義寺滚,則 React 會分配默認 props,但如果你將null
作為 prop 的值屈雄,它將保持null
村视。
const ShoppingCart = (props) => {
return (
<div>
<h1>Shopping Cart Component</h1>
</div>
)
};
ShoppingCart.defaultProps = {
items: 0
};
React:覆蓋默認的 Props
在 React 中,設(shè)置默認的 props 是一個很有用的特性酒奶,顯式設(shè)置組件的 prop 值即可覆蓋默認 props蚁孔。
const Items = (props) => {
return <h1>Current Quantity of Items in Cart: {props.quantity}</h1>
}
Items.defaultProps = {
quantity: 0
}
class ShoppingCart extends React.Component {
constructor(props) {
super(props);
}
render() {
return <Items quantity={10} />
}
};
React:使用 PropTypes 來定義你期望的 Props
React 提供了有用的類型檢查特性奶赔,以驗證組件是否接收了正確類型的 props。例如杠氢,你的應(yīng)用程序調(diào)用 API 來檢索你希望在數(shù)組中的數(shù)據(jù)站刑,然后將數(shù)據(jù)作為 prop 傳遞給組件。你可以在組件上設(shè)置propTypes
鼻百,以要求數(shù)據(jù)的類型為array
绞旅。當數(shù)據(jù)是任何其他類型時,都會拋出警告温艇。
// 在 7 種 JavaScript 基本類型中因悲,function和boolean(寫為bool)是僅有的使用異常拼寫的兩種類型
MyComponent.propTypes = { handleClick: PropTypes.func.isRequired }
// 在 React v15.5.0 版本中, PropTypes可以從 React 中單獨引入
import React, { PropTypes } from 'react';
const Items = (props) => {
return <h1>Current Quantity of Items in Cart: {props.quantity}</h1>
};
Items.propTypes = {
quantity: PropTypes.number.isRequired
};
Items.defaultProps = {
quantity: 0
};
class ShoppingCart extends React.Component {
constructor(props) {
super(props);
}
render() {
return <Items />
}
};
React:使用 this.props 訪問 Props
class ReturnTempPassword extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<p>Your temporary password is: <strong>{this.props.tempPassword}</strong></p>
</div>
);
}
};
class ResetPassword extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h2>Reset Password</h2>
<h3>We've generated a new temporary password for you.</h3>
<h3>Please reset this password from your account settings ASAP.</h3>
<ReturnTempPassword tempPassword='qweasdzxc' />
</div>
);
}
};
React:復(fù)習如何使用 Props 和無狀態(tài)函數(shù)組件
無狀態(tài)函數(shù)組件是一個函數(shù),它接收 props 作為輸入并返回 JSX勺爱。另一方面晃琳,無狀態(tài)組件是一個類,它擴展了React.Component
琐鲁,但是不使用內(nèi)部狀態(tài)卫旱。最后,狀態(tài)組件是指維護其自身內(nèi)部狀態(tài)的組件围段,它簡稱組件或 React 組件顾翼。
class CampSite extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<Camper name='Hello React!' />
</div>
);
}
};
const Camper = props => (<p>{props.name}</p>);
Camper.defaultProps = {
name: 'CamperBot'
};
Camper.propTypes = {
name: PropTypes.string.isRequired
};
React:創(chuàng)建一個有狀態(tài)的組件
React中最重要的主題之一是state
。 state 包含應(yīng)用程序需要了解的任何數(shù)據(jù)奈泪,這些數(shù)據(jù)可能會隨時間而變化暴构。
你可以通過在constructor
中的組件類上聲明state
屬性來在 React 組件中創(chuàng)建 state,它在創(chuàng)建時使用state
初始化組件段磨。state
屬性必須設(shè)置為 JavaScript對象
取逾。聲明如下:
class StatefulComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'HJSD'
};
}
render() {
return (
<div>
<h1>{this.state.name}</h1>
</div>
);
}
};
你可以在組件的整個生命周期內(nèi)訪問state
對象,你可以更新它苹支、在 UI 中渲染它砾隅,也可以將其作為 props 傳遞給子組件。
React:在用戶界面中渲染狀態(tài)
如果你想在 render 方法的return
中訪問 state 值债蜜,你必須把這個值用花括號括起來晴埂。
React 使用所謂的虛擬 DOM 來跟蹤幕后的變化。當 state 數(shù)據(jù)更新時寻定,它會使用該數(shù)據(jù)觸發(fā)組件的重新渲染--包括接收 prop 數(shù)據(jù)的子組件儒洛。React 只在必要的時候更新實際的DOM,這意味著你不必擔心 DOM 的變更狼速,只需聲明 UI 的外觀即可琅锻。
注意,如果組件有狀態(tài),則沒有其他組件知道它的state
恼蓬。它的state
是完全封裝的惊完,或者是局限于組件本身的,除非你將 state 數(shù)據(jù)作為props
傳遞給子組件处硬。
封裝state
的概念非常重要小槐,因為它允許你編寫特定的邏輯,然后將該邏輯包含并隔離在代碼中的某個位置荷辕。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'freeCodeCamp'
}
}
render() {
return (
<div>
<h1>{this.state.name}</h1>
</div>
);
}
};
React:以另一種方式在用戶界面中渲染狀態(tài)
在render()
方法中凿跳,在return
語句之前,你可以直接編寫 JavaScript疮方。例如控嗜,你可以聲明函數(shù)、從state
或props
訪問數(shù)據(jù)案站、對此數(shù)據(jù)執(zhí)行計算等躬审。然后棘街,你可以將任何數(shù)據(jù)賦值給你在return
語句中可以訪問的變量蟆盐。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'freeCodeCamp'
}
}
render() {
const name = this.state.name;
return (
<div>
<h1>{name}</h1>
</div>
);
}
};
React:用 this.setState 設(shè)置狀態(tài)
React 提供了setState
方法來更新組件的state
。在組件類中調(diào)用setState
方法如下所示:this.setState()
遭殉,傳入鍵值對的對象石挂,其中鍵是 state 屬性,值是更新后的 state 數(shù)據(jù)险污。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'Initial State'
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
name: 'React Rocks!'
});
}
render() {
return (
<div>
<button onClick={this.handleClick}>Click Me</button>
<h1>{this.state.name}</h1>
</div>
);
}
};
React 希望你永遠不要直接修改state
痹愚,而是在 state 發(fā)生改變時始終使用this.setState()
。此外蛔糯,React 可以批量處理多個 state 更新以提高性能拯腮。這意味著通過setState
方法進行的 state 更新可以是異步的
。setState
方法有一種替代語法可以解決異步問題蚁飒,雖然這很少用到动壤,但是最好還是記住它!React 文檔
React:將 this 綁定到 Class 方法
有幾種方法可以讓你的類方法訪問this
淮逻。
一種常見的方法是在構(gòu)造函數(shù)中顯式地綁定this
琼懊,這樣當組件初始化時,this
就會綁定到類方法爬早。this.handleClick = this.handleClick.bind(this)
用于其在構(gòu)造函數(shù)中的handleClick
方法哼丈。然后,當你在類方法中調(diào)用像this.setState()
這樣的函數(shù)時筛严,this
指的是這個類醉旦,而不是undefined
。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
itemCount: 0
};
this.addItem = this.addItem.bind(this);
}
addItem() {
this.setState({
itemCount: this.state.itemCount + 1
});
}
render() {
return (
<div>
<button onClick={this.addItem}>Click Me</button>
<h1>Current Item Count: {this.state.itemCount}</h1>
</div>
);
}
};
React:使用 State 切換元素
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
visibility: false
};
this.toggleVisibility = this.toggleVisibility.bind(this);
}
toggleVisibility(){
this.state.visibility = !this.state.visibility;
}
render() {
if (this.state.visibility) {
return (
<div>
<button onClick={this.toggleVisibility}>Click Me</button>
<h1>Now you see me!</h1>
</div>
);
} else {
return (
<div>
<button onClick={this.toggleVisibility}>Click Me</button>
</div>
);
}
}
};
React:寫一個簡單的計數(shù)器
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
this.increment = this.increment.bind(this);
this.decrement = this.decrement.bind(this);
this.reset = this.reset.bind(this);
}
increment(){
this.setState({ count: this.state.count + 1 });
}
decrement(){
this.setState({ count: this.state.count - 1 });
}
reset(){
this.setState({ count: 0 });
}
render() {
return (
<div>
<button className='inc' onClick={this.increment}>Increment!</button>
<button className='dec' onClick={this.decrement}>Decrement!</button>
<button className='reset' onClick={this.reset}>Reset</button>
<h1>Current Count: {this.state.count}</h1>
</div>
);
}
};
React:創(chuàng)建一個可以控制的輸入框
class ControlledInput extends React.Component {
constructor(props) {
super(props);
this.state = {
input: ''
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event){
this.setState({
input: event.target.value
})
}
render() {
return (
<div>
<input type="text" value={this.state.input} onChange={this.handleChange} />
<h4>Controlled Input:</h4>
<p>{this.state.input}</p>
</div>
);
}
};
React:創(chuàng)建一個可以控制的表單
class MyForm extends React.Component {
constructor(props) {
super(props);
this.state = {
input: '',
submit: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({
input: event.target.value,
submit: ''
});
}
handleSubmit(event) {
event.preventDefault();
this.setState({
input: '',
submit: this.state.input
});
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input value={this.state.input} onChange={this.handleChange}/>
<button type='submit' onSubmit={this.handleSubmit}>Submit!</button>
</form>
<h1>{this.state.submit}</h1>
</div>
);
}
};
React:將 State 作為 Props 傳遞給子組件
props 是從哪里來的。一個常見的模式是:有狀態(tài)組件中包含對應(yīng)用程序很重要的state
髓抑,然后用它渲染子組件咙崎。你希望這些組件能夠訪問該state
的某些部分,就把這些部分作為 props 傳入吨拍。
例如褪猛,也許你有一個App
組件可以渲染Navbar
以及其他組件。在你的App
中羹饰,你的state
中包含大量用戶信息伊滋,但是Navbar
只需要訪問用戶的用戶名就可以顯示出來,這時你將該state
作為一個 prop 傳遞給Navbar
組件即可队秩。
這個模式說明了 React 中的一些重要范例笑旺。第一個是單向數(shù)據(jù)流,state 沿著應(yīng)用程序組件樹的一個方向流動馍资,從有狀態(tài)父組件到子組件筒主,子組件只接收它們需要的 state 數(shù)據(jù)。第二鸟蟹,復(fù)雜的有狀態(tài)應(yīng)用程序可以分解成幾個乌妙,或者可能是一個單一的有狀態(tài)組件。其余組件只是從父組件簡單的接收 state 作為 props建钥,并從該 state 渲染 UI藤韵。
它開始創(chuàng)建一種分離,在這種分離中熊经,state 管理在代碼的一部分中處理泽艘,而 UI 渲染在另一部分中處理。將 state 邏輯與 UI 邏輯分離是 React 的關(guān)鍵原則之一镐依。當它被正確使用時匹涮,它使得復(fù)雜的、有狀態(tài)的應(yīng)用程序的設(shè)計變得更容易管理槐壳。
class MyApp extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'CamperBot'
}
}
render() {
return (
<div>
<Navbar name={this.state.name} />
</div>
);
}
};
class Navbar extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h1>Hello, my name is: {this.props.name} </h1>
</div>
);
}
};
React:傳遞回調(diào)作為 Props
class MyApp extends React.Component {
constructor(props) {
super(props);
this.state = {
inputValue: ''
}
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({
inputValue: event.target.value
});
}
render() {
return (
<div>
<GetInput input={this.state.inputValue} handleChange={this.handleChange} />
<RenderInput input={this.state.inputValue} />
</div>
);
}
};
class GetInput extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h3>Get Input:</h3>
<input
value={this.props.input}
onChange={this.props.handleChange}/>
</div>
);
}
};
class RenderInput extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h3>Input Render:</h3>
<p>{this.props.input}</p>
</div>
);
}
};
React:使用生命周期方法:componentWillMount
React 組件有幾種特殊方法然低,可以在組件生命周期的特定點執(zhí)行操作。這些稱為生命周期方法或生命周期鉤子宏粤,允許你在特定時間點捕獲組件脚翘。這可以在渲染之前、更新之前绍哎、接收 props 之前来农、卸載之前等等。以下是一些主要生命周期方法的列表:
componentWillMount()
componentDidMount()
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
componentDidUpdate()
componentWillUnmount()
React:使用生命周期方法:componentDidMount
React 的最佳實踐是在生命周期方法componentDidMount()
中對服務(wù)器進行 API 調(diào)用或任何其他調(diào)用崇堰。將組件裝載到 DOM 后會調(diào)用此方法沃于。此處對setState()
的任何調(diào)用都將觸發(fā)組件的重新渲染涩咖。在此方法中調(diào)用 API 并使用 API?? 返回的數(shù)據(jù)設(shè)置 state 時,一旦收到數(shù)據(jù)繁莹,它將自動觸發(fā)更新檩互。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
activeUsers: null
};
}
componentDidMount() {
setTimeout( () => {
this.setState({
activeUsers: 1273
});
}, 2500);
}
render() {
return (
<div>
<h1>Active Users: { this.state.activeUsers }</h1>
</div>
);
}
};
React:添加事件偵聽器
componentDidMount()方法也是添加特定功能所需的任何事件監(jiān)聽器的最佳位置。
React 的合成事件系統(tǒng)非常適合用于你在 DOM 元素上管理的大多數(shù)交互咨演。但是闸昨,如果要將事件處理程序附加到 document 或 window 對象,則必須直接執(zhí)行此操作薄风。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
message: ''
};
this.handleEnter = this.handleEnter.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this);
}
componentDidMount() {
document.addEventListener('keydown', this.handleKeyPress)
}
componentWillUnmount() {
document.removeEventListener('keydown', this.handleKeyPress)
}
handleEnter() {
this.setState({
message: this.state.message + 'You pressed the enter key! '
});
}
handleKeyPress(event) {
if (event.keyCode === 13) {
this.handleEnter();
}
}
render() {
return (
<div>
<h1>{this.state.message}</h1>
</div>
);
}
};
React:使用生命周期方法管理更新
另一個生命周期方法是componentWillReceiveProps()
饵较,只要組件將要接收新的 props 就會調(diào)用它。此方法接收新的 props(通常寫為nextProps
)作為參數(shù)遭赂。
還有一個方法是componentDidUpdate()
循诉,它在組件重新渲染后立即調(diào)用。請注意撇他,渲染和裝載在組件生命周期中是不同的茄猫。當頁面第一次加載時,所有組件都被裝載困肩,這就是調(diào)用componentWillMount()
和componentDidMount()
等方法的地方划纽。此后,隨著 state 的變化僻弹,組件會重新渲染自己阿浓。
class Dialog extends React.Component {
constructor(props) {
super(props);
}
componentWillUpdate() {
console.log('Component is about to update...');
}
componentWillReceiveProps(nextProps){
console.log("this.props: "+this.props)
console.log('nextProps: '+nextProps);
}
componentDidUpdate(){
console.log('componentDidUpdate');
}
render() {
return <h1>{this.props.message}</h1>
}
};
class Controller extends React.Component {
constructor(props) {
super(props);
this.state = {
message: 'First Message'
};
this.changeMessage = this.changeMessage.bind(this);
}
changeMessage() {
this.setState({
message: 'Second Message'
});
}
render() {
return (
<div>
<button onClick={this.changeMessage}>Update</button>
<Dialog message={this.state.message}/>
</div>
);
}
};
React:使用 shouldComponentUpdate 優(yōu)化重新渲染
如果任何組件接收到新的state
或新的props
他嚷,它會重新渲染自己及其所有子組件蹋绽。這通常是好的。但是 React 提供了一種生命周期方法筋蓖,當子組件接收到新的state
或props
時卸耘,你可以調(diào)用該方法,并特別聲明組件是否應(yīng)該更新粘咖。方法是shouldComponentUpdate()
蚣抗,它將nextProps
和nextState
作為參數(shù)。
這種方法是優(yōu)化性能的有效方法瓮下。例如翰铡,默認行為是,當組件接收到新的props時讽坏,即使props
沒有改變锭魔,它也會重新渲染。你可以通過使用shouldComponentUpdate()
比較props
來防止這種情況路呜。
該方法必須返回一個布爾值迷捧,該值告訴 React 是否更新組件织咧。你可以比較當前的 props(this.props
)和下一個 props(nextProps
),以確定你是否需要更新漠秋,并相應(yīng)地返回true
或false
笙蒙。
class OnlyEvens extends React.Component {
constructor(props) {
super(props);
}
shouldComponentUpdate(nextProps, nextState) {
console.log('Should I update?');
return nextProps.value % 2 === 0;
}
componentWillReceiveProps(nextProps) {
console.log('Receiving new props...');
}
componentDidUpdate() {
console.log('Component re-rendered.');
}
render() {
return <h1>{this.props.value}</h1>
}
};
class Controller extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 0
};
this.addValue = this.addValue.bind(this);
}
addValue() {
this.setState({
value: this.state.value + 1
});
}
render() {
return (
<div>
<button onClick={this.addValue}>Add</button>
<OnlyEvens value={this.state.value}/>
</div>
);
}
};
React:介紹內(nèi)聯(lián)樣式
如何對在 React 中創(chuàng)建的 JSX 元素進行風格化。如果從樣式表導入樣式庆锦,它就沒有太大的不同捅位。使用className
屬性將 class 應(yīng)用于 JSX 元素,并將樣式應(yīng)用于樣式表中的 class搂抒。另一種選擇是使用內(nèi)聯(lián)
樣式绿渣,這在 ReactJS 開發(fā)中非常常見。
// HTML 中內(nèi)聯(lián)樣式
<div style="color: yellow; font-size: 16px">Mellow Yellow</div>
// JSX 元素使用style屬性
<div style={{color: "yellow", fontSize: 16}}>Mellow Yellow</div>
class Colorful extends React.Component {
render() {
return (
<div style={{fontSize:"72px",color:"red"}}>Big Red</div>
);
}
};
React:在 React 中添加內(nèi)聯(lián)樣式
所有屬性值是長度的(如height
燕耿、width
和fontSize
)其單位都假定為px
中符。例如,如果要使用em
誉帅,可以用引號將值和單位括起來淀散,例如{fontSize: "4em"}
。除了默認為px
的長度值之外蚜锨,所有其他屬性值都應(yīng)該用引號括起來档插。
const styles = {fontSize: 40, color: "purple", border:"2px solid purple"};
class Colorful extends React.Component {
render() {
return (
<div style={styles}>Style Me!</div>
);
}
};
React:在 React Render 方法中使用 JavaScript
在render
方法中編寫 JavaScript,你可以把 JavaScript 直接放在return
語句之前亚再,而不必將其插入大括號中郭膛。這是因為它還不在 JSX 代碼中。當你稍后想在return
語句中的 JSX 代碼中使用變量時氛悬,可以將變量名放在大括號中则剃。
render() {
const possibleAnswers = [
'It is certain',
'It is decidedly so',
'Without a doubt',
'Yes, definitely',
'You may rely on it',
'As I see it, yes',
'Outlook good',
'Yes',
'Signs point to yes',
'Reply hazy try again',
'Ask again later',
'Better not tell you now',
'Cannot predict now',
'Concentrate and ask again',
'Don\'t count on it',
'My reply is no',
'My sources say no',
'Most likely',
'Outlook not so good',
'Very doubtful'
];
const answer = possibleAnswers[this.state.randomIndex];
return (...)
}
React:使用 If/Else 條件進行渲染
使用 JavaScript 控制渲染視圖的另一個應(yīng)用是將渲染的元素綁定到一個條件。當條件為真時如捅,將呈現(xiàn)一個視圖棍现,反之,則呈現(xiàn)另一種視圖镜遣。你可以在 React 組件的render()方法中使用的標準if/else語句來實現(xiàn)這一點己肮。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
display: true
}
this.toggleDisplay = this.toggleDisplay.bind(this);
}
toggleDisplay() {
this.setState({
display: !this.state.display
});
}
render() {
if(this.state.display){
return (
<div>
<button onClick={this.toggleDisplay}>Toggle Display</button>
<h1>Displayed!</h1>
</div>
);
}else {
return (
<div>
<button onClick={this.toggleDisplay}>Toggle Display</button>
</div>
);
}
}
};
React:使用 && 獲得更簡潔的條件
if/else 語句在上一次挑戰(zhàn)中是有效的,但是有一種更簡潔的方法可以達到同樣的結(jié)果悲关。你可以使用&&
邏輯運算符以更簡潔的方式執(zhí)行條件邏輯谎僻。
{condition && <p>markup</p>}
render() {
return (
<div>
<button onClick={this.toggleDisplay}>Toggle Display</button>
{this.state.display && <h1>Displayed!</h1>}
</div>
);
}
React:使用三元表達式進行條件渲染
在繼續(xù)使用動態(tài)渲染技術(shù)之前,還有最后一種方法可以渲染你想要的東西寓辱,它使用內(nèi)置的 JavaScript 條件:三元運算符艘绍。
const inputStyle = {
width: 235,
margin: 5
}
class CheckUserAge extends React.Component {
constructor(props) {
super(props);
this.state = {
input: '',
userAge: ''
};
this.submit = this.submit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.setState({
input: e.target.value,
userAge: ''
});
}
submit() {
this.setState({
userAge: this.state.input
});
}
render() {
const buttonOne = <button onClick={this.submit}>Submit</button>;
const buttonTwo = <button>You May Enter</button>;
const buttonThree = <button>You Shall Not Pass</button>;
return (
<div>
<h3>Enter Your Age to Continue</h3>
<input
style={inputStyle}
type="number"
value={this.state.input}
onChange={this.handleChange} /><br />
{
this.state.userAge===''?buttonOne: (this.state.userAge < 18?buttonThree:buttonTwo)
}
</div>
);
}
};
React:根據(jù) Props 有條件地渲染
使用 props 有條件地渲染代碼在 React 開發(fā)人員中很常見--也就是說:他們使用給定 prop 的值來自動決定渲染什么。
class Results extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<h1>
{
this.props.fiftyFifty
}
</h1>
)
};
};
class GameOfChance extends React.Component {
constructor(props) {
super(props);
this.state = {
counter: 1
}
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
counter: this.state.counter+1
});
}
render() {
let expression = Math.random() > 0.5;
return (
<div>
<button onClick={this.handleClick}>Play Again</button>
{(expression == 1)? <Results fiftyFifty="You win!"/> : <Results fiftyFifty="You lose!"/> }
<p>{'Turn: ' + this.state.counter}</p>
</div>
);
}
};
React:根據(jù)組件狀態(tài)有條件地更改內(nèi)聯(lián) CSS
根據(jù) React 組件的 state 有條件地渲染 CSS讶舰。要執(zhí)行此操作鞍盗,請檢查條件需了,如果滿足該條件,則修改在 render 方法中分配給 JSX 元素的樣式對象般甲。
class GateKeeper extends React.Component {
constructor(props) {
super(props);
this.state = {
input: ''
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({ input: event.target.value })
}
render() {
let inputStyle = {
border: '1px solid black'
};
if(this.state.input.length > 15){
inputStyle.border = '3px solid red';
}
return (
<div>
<h3>Don't Type Too Much:</h3>
<input
type="text"
style={inputStyle}
value={this.state.input}
onChange={this.handleChange} />
</div>
);
}
};
React:使用 Array.map() 動態(tài)渲染元素
const textAreaStyles = {
width: 235,
margin: 5
};
class MyToDoList extends React.Component {
constructor(props) {
super(props);
this.state = {
userInput: '',
toDoList: []
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleSubmit() {
const itemsArray = this.state.userInput.split(',');
this.setState({
toDoList: itemsArray
});
}
handleChange(e) {
this.setState({
userInput: e.target.value
});
}
render() {
const items = this.state.toDoList.map(i => <li>{i}</li>);;
return (
<div>
<textarea
onChange={this.handleChange}
value={this.state.userInput}
style={textAreaStyles}
placeholder="Separate Items With Commas" /><br />
<button onClick={this.handleSubmit}>Create List</button>
<h1>My "To Do" List:</h1>
<ul>
{items}
</ul>
</div>
);
}
};
React:給同級元素一個唯一的鍵屬性
const frontEndFrameworks = [
'React',
'Angular',
'Ember',
'Knockout',
'Backbone',
'Vue'
];
function Frameworks() {
const renderFrameworks = frontEndFrameworks.map(x => <li key={x+1}>{x}</li>);
return (
<div>
<h1>Popular Front End JavaScript Frameworks</h1>
<ul>
{renderFrameworks}
</ul>
</div>
);
};
使用 Array.Filter() 動態(tài)過濾數(shù)組
filter
它根據(jù)條件過濾數(shù)組的內(nèi)容肋乍,然后返回一個新數(shù)組。例如敷存,如果你有一個 users 數(shù)組墓造,每個數(shù)組元素都有一個可以設(shè)置為true
或false
的online
屬性,你可以只過濾那些在線的用戶:let onlineUsers = users.filter(user => user.online);
const usersOnline = this.state.users.filter(i => i.online == true);
const renderOnline = usersOnline.map((i) => <li key={i.username + 1}>{i.username}</li>);
React:用 renderToString 在服務(wù)器上渲染 React
由于 React 是一個 JavaScript 視圖庫锚烦,所以使用 Node 讓 JavaScript 運行在服務(wù)器上是可行的觅闽。事實上,React 提供了一個可用于此目的的renderToString()
方法涮俄。renderToString()
方法由ReactDOMServer
提供蛉拙。
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return <div/>
}
};
ReactDOMServer.renderToString(<App />);