react中文文檔
以下文字均為看文檔后的筆記
用引號來定義以字符串為值的屬性
const element = <div tabIndex="0"></div>;
用大括號來定義以 JavaScript 表達式為值的屬性(使用了大括號包裹的 JavaScript 表達式時就不要再到外面套引號了。因為JSX 會將引號當中的內容識別為字符串而不是表達式)
const element = <img src={user.avatarUrl}></img>;
JSX使用 camelCase 小駝峰命名 來定義屬性的名稱
JSX所有的內容在渲染之前都被轉換成了字符串。這樣可以有效地防止XSS攻擊。
Babel 轉譯器會把 JSX 轉換成一個名為 React.createElement() 的方法調用。
//原先
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
//轉換后
const element = React.createElement(
'h1',//第一個是tagname
{className: 'greeting'},//第二個是屬性,如果沒有則為null
'Hello, world!'//第三個是內容即children,如果是嵌套的就會在這里循環下去
);
React 元素都是不可變的。當元素被創建之后,你是無法改變其內容或屬性的,更新界面的唯一辦法是創建一個新的元素,然后將它傳入 ReactDOM.render() 方法
React 只會更新必要的部分,React DOM 首先會比較元素內容先后的不同,而在渲染過程中只會更新改變了的部分
functional component和class component
當React遇到的元素是用戶自定義的組件,它會將JSX屬性作為單個對象傳遞給該組件,這個對象稱之為“props”。
const element = <Welcome name="Sara" />;
//這段中 name='Sara' 會作為參數即props:{name:'Sara'}傳入Welcome并調用Welcome
組件名稱必須以大寫字母開頭
組件嵌套時,頂部的組件返回值只能有一個根元素
State是組件自己私有的屬性,所以不同于props不能改變,可以通過調用setState()來改變state
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({ //setState()是唯一可以改變state的入口
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
數據自頂向下流動,組件可以選擇將其狀態作為屬性傳遞給其子組件,但是子組件無法知道其來源
<FormattedDate date={this.state.date} />
function FormattedDate(props) {
return <h2>It is {props.date.toLocaleTimeString()}.</h2>;
}
在React中必須明確的使用 preventDefault 來阻止默認行為,不能使用返回false來阻止
class Clock extends React.Component {
render(){
return (
<div>
<a href="baidu.com" onClick={abc}>百度首頁</a>
<h1>Hello, world!</h1>
</div>
);
}
}
function abc(e){
e.preventDefault()
console.log('The link was clicked.')
//return false //這段會無效,頁面依舊跳轉
}
reactDom.render(
<Clock/>,
document.getElementById('root')
)
通過 bind 方式向監聽函數傳參,在類組件中定義的監聽函數,事件對象 e 要排在所傳遞參數的后面
fn(name,e){}
受控組件,在React中,可變的狀態通常保存在組件的狀態屬性中,并且只能用setState() 方法進行更新.
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
//input的value存儲在state中,改變時調用setState,
在React中,<textarea>會用value屬性來代替,用法類似input.
<textarea value={this.state.value} onChange={this.handleChange} />
select標簽的selected是由select標簽上的value屬性置頂,而不是option
constructor(props) {
super(props);
this.state = {value: 'coconut'};
-------
<select value={this.state.value} onChange={this.handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
以上三種都十分類似,都是通過傳入一個value屬性來實現對組件的控制。
當你有處理多個受控的input元素時,你可以通過給每個元素添加一個name屬性,來讓處理函數根據 event.target.name的值來選擇做什么。
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
//效果類似過濾
狀態提升,遇到幾個組件需要共用狀態數據的情況。這種情況下,將這部分共享的狀態提升至他們最近的父組件當中進行管理,即其中一個子組件變化時另一個子組件也會變,與之前不同的是,子組件的props將由父組件提供,包括change的方法,因為change是父組件的方法所以可以改變父組件的state,從而影響子組件
在應用中應保持自上而下的數據流,而不是嘗試在不同組件中同步狀態。
React 具有強大的組合模型,我們建議使用組合而不是繼承來復用組件之間的代碼。
JSX 標簽內的任何內容都將通過 children 屬性傳入組件。由于組件在一個 <div> 內渲染了 {props.children},所以被傳遞的所有元素都會出現在最終輸出中。屬性不限于children,也可以是自己約定的屬性
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
這時 children屬性為
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
在較為簡單的例子中,通常自頂向下更容易,而在較大的項目中,自底向上會更容易并且在你構建的時候有利于編寫測試
react key概述
react中的key屬性,它是一個特殊的屬性,它是出現不是給開發者用的(例如你為一個組件設置key之后不能獲取組件的這個key props),而是給react自己用的。
簡單來說,react利用key來識別組件,它是一種身份標識標識,就像我們的身份證用來辨識一個人一樣。每個key對應一個組件,相同的key react認為是同一個組件,這樣后續相同的key對應組件都不會被創建
users: [
{id:1,name: '張三'},
{id:2, name: '李四'},
{id: 2, name: "王五"}
]
比如這樣的數據中,王五不會被渲染,主要是因為react根據key認為李四和王五是同一個組件,導致第一個被渲染,后續的會被丟棄掉。
key不是用來提升react的性能的,不過用好key對性能是有幫助的的。
參考資料
React之key詳解
大寫開頭的 JSX 標簽表示一個 React 組件。這些標簽將會被編譯為同名變量并被引用,所以如果你使用了 <Foo /> 表達式,則必須在作用域中先聲明 Foo 變量。
React 會將小寫開頭的標簽名認為是 HTML 原生標簽
你不能使用表達式來直接作為 React 元素的標簽
const components = {
photo: PhotoStory,
video: VideoStory
};
const SpecificStory = components[props.storyType];
return <SpecificStory story={props.story} />;
//比如這樣先賦值給SpecificStory這樣的大寫開頭的變量
if 語句和 for 循環在 JavaScript 中不是表達式,因此它們不能直接在 JSX 中使用,但是你可以將它們放在周圍的代碼中。
<MyComponent foo={1 + 2 + 3 + 4} />
function NumberDescriber(props) {
let description;
if (props.number % 2 == 0) {
description = <strong>even</strong>;
} else {
description = <i>odd</i>;
}
return <div>{props.number} is an {description} number</div>;
}
你可以將字符串常量作為屬性值傳遞,react不會對其進行HTML轉義
<MyComponent message={'hello world'} />
React 組件也可以通過數組的形式返回多個元素,會按順序渲染
false、null、undefined 和 true 都是有效的子代,但它們不會直接被渲染。下面的表達式是等價的:
<div />
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>
<div>{true}</div>
JavaScript 中的一些“falsy” 值(比如數字0
),它們依然會被渲染
<div>
{props.messages.length &&
<MessageList messages={props.messages} />
}
</div>
//當props.messages為空數組時,會打印0
要解決這個問題,請確保 && 前面的表達式始終為布爾值
<div>
{props.messages.length > 0 &&
<MessageList messages={props.messages} />
}
</div>