7.Redis詳解(七)------ AOF 持久化
JSX
const element=<h1>hello,world</h1>;
JSX是javascript的語法拓展,JSX產生react元素。
react是使用包含標記和邏輯共同放到元件中來實現分離關注點。react不強制使用JSX,但是JSX作為輔助和UI一起很有用,它能讓React顯示更多有用的錯誤和警告訊息。
在JSX中嵌入表示式
const name='zyy';
const element=<h1>hello,{name}</h1>;【{}內可以是2+2,user.name,fn(user)】
ReactDom.render(
element,
document.getElementById('root');
);
呼叫JavaScript函式的結果嵌入fn(user)
到<h1>
元素中
function fn(user){
return user.firstName+' '+user.lastName;
}
const user={
firstName:'zhu',
lastName:'Yuanyuan'
}
const element=(
<h1>
hello,{fn(user)}!
</h1>
);
ReactDom.render{
element,
document.getElementById('root')
};
在編譯之後,JSX 表示式會被轉為普通 JavaScript 函式呼叫,並且對其取值後得到 JavaScript 物件。,即在if
語句和for
迴圈內部可以使用JSX
使用JSX指定屬性
可以通過使用引號,來將屬性值指定為字串字面量:
const element=<div tabIndex="0"></div>
也可以使用大括號,在屬性值中插入一個 JavaScript 表示式:
const element=<img src={user.url}></img>
使用 JSX 指定子元素
假如一個標籤裡面沒有內容,你可以使用/>
const element = <img src={user.avatarUrl} />;
JSX 標籤裡能夠包含很多子元素:
const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);
JSX防止XSS攻擊
React DOM 在渲染所有輸入內容之前,預設會進行轉義。它可以確保在你的應用中,永遠不會注入那些並非自己明確編寫的內容。所有的內容在渲染之前都被轉換成了字串,因此惡意程式碼無法成功注入,從而有效地防止了 XSS 攻擊。
JSX表示物件
Babel將JSX編譯為React.createElement()
呼叫。
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
從本質上講,React.creatElement()會建立一個像這樣的物件:
// Note: this structure is simplified
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world!'
}
};
這些物件叫“React元素”,它們描述了你希望在螢幕上看到的內容。React讀取這些物件然後使用它們來構建 DOM 以及保持隨時更新
元素渲染
元素是構成 React 應用的最小磚塊,React DOM 會負責更新 DOM 來與 React 元素保持一致。
想要將一個 React 元素渲染到根 DOM 節點中,只需把它們一起傳入ReactDOM.render()
:
react元素是不可變物件,建立元素後,就無法更改它的子元素或屬性。一個元素代表了某一時刻的UI。
時鐘案例:
function tick(){
const element=(
<div>
<h1>hello,world</h1>
<h2>{new Date().toLocaleTimeString()}</h2>
</div>
);
ReactDom.render(element,document.getElementById('root'));
}
setIntervel(tick,1000);
React 只更新它需要更新的部分
元件和props
元件允許你分隔UI為獨立的、可重用的零件,每個零件是隔離的。
概念上,元件就像js的函式。它們接收任意的輸入(被稱為 'props'),並返回React元素,用以描述應該在螢幕上顯示的內容。
函式元件和class元件
函式元件
function Welcome(props){
return <h1>hello,{props.name}</h1>;【它接收單個的 'props' 物件引數,並返回一個 'React元素'】
}
class元件
class Welcome extends React.component{
render(){
return <h1>hello,{this.props.name}</h1>;
}
}
element也能代表使用者定義的元件:
當 React 元素為使用者自定義元件時,它會將 JSX 所接收的屬性(attributes)以及子元件(children)轉換為單個物件傳遞給元件,這個物件被稱之為 “props”。
function Welcome(props){
return <h1>hello,{props.name}</h1>;
}
const element=<Welcome name="zyy"/>;
ReactDom.render(
element,
document.getElementById('root')
);
注:元件名首字母大寫。
組合元件
元件可以在其輸出中引用其他元件。這就可以讓我們用同一組件來抽象出任意層次的細節。
例子:建立一個app元件,多次渲染welcome元件
function Welcome(props){
return <h1>hello,{props.name}</h1>;
}
function App(){
return( <div>
<Welcome name="zhu" />
<Welcome name="Yuan" />
<Welcome name="yuan" />
</div>
);
}
ReactDom.render(
<App />,
document.getElementById('root')
);
props是隻讀的
props會傳遞給元件,所以不能修改props
state和生命週期
state類似props,但是它是私有的,並且完全由元件控制。
將函式轉換為類
- 建立一個具有相同名稱的,可擴充套件的ES6類
React.Component
。 - 向其中新增一個名為的空方法
render()
。 - 將函式的主體移到
render()
方法中。 - 更換
props
用this.props
的render()
身體。 - 刪除剩餘的空函式宣告。
Clock extends React.Component{
render(){
return (
<div>
<h1>hello,world</h1>
<h2>It is {this.props.date.toLocalETimeString()}</h2>
</div>
);
}
}
function tick(){
ReactDom.render(
<Clock date={new Date()} />,
document.getElementById('root')
);
}
setInterval(tick,1000);
向類中新增區域性state
通過3步,將props中的data移動到state。
- 在方法中替換
this.props.date
為:this.state.date
- 新增一個分配初始值的類建構函式
this.state
: date
從<Clock />
元素中刪除道具:
Clock extends React.Component{
constructor(props){
super(props);
this.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')
);
將生命週期方法新增到類中
clock元件首次渲染為dom時,我們設定了一個計時器(set up a timer)。這在React中,被稱作 'mounting'
當移除由clock元件產生的dom時,我們清除mount設定的計時器。這在React中,被稱作 'unmouting'
我們可以在元件類中,宣告一些特殊的方法,當元件 mount 和 unmount 時,來執行我們設定的程式碼:
Clock extends React.Component{
constructor(props){
super(props);
this.state={date: new Date()};
}
componentDidMount(){
}
componentWillUnmount(){
}
render(){
return (
<div>
<h1>hello,world</h1>
<h2>It is {this.state.date.toLocalETimeString()}</h2>
</div>
);
}
}
元件輸出已經被渲染為dom後,執行 'componentDidMount()' 鉤子。這是個設定計時器的好地方:
componentDidMount(){
this.timerId=setInterval(
()=>this.tick(),1000
);
}
this.props由React自身建立,而this.state有特殊的意義,如果你需要儲存一些資料,且這些資料並不用於可見輸出(the visual output),你可以手動給元件類新增額外的欄位
如果你在 render() 中不使用其他欄位,則不應該在 state 中新增這些欄位
在 'componentWillUnmount' 生命週期鉤子中,清除計時器:
componentWillUnmount(){
clearInterval(this.timerId);
}
實現tick():
tick() {
this.setState({
date: new Date()
});
}
整個程式碼:
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({
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')
);
正確使用state
1.不要直接修改狀態,而是使用setState()。建構函式是唯一可以給this.state
賦值的地方:
// Wrong
this.state.comment = 'Hello';
// Correct
this.setState({comment: 'Hello'});
2.state的更新可能是非同步的。
出於效能考慮,React 可能會把多個setState()
呼叫合併成一個呼叫。
因為this.props
和this.state
可能會非同步更新,所以你不要依賴他們的值來更新下一個狀態。
為了解決這個問題,可以讓setState()
接收一個函式而不是一個物件。
這個函式用上一個 state 作為第一個引數,將此次更新被應用時的 props 做為第二個引數:
// Correct
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
3.state的更新會被合併
當你呼叫setState()
的時候,React 會把你提供的物件合併到當前的 state。
4.state 為區域性的原因:只有擁有並設定state的元件能訪問到state,其他元件都無法訪問。
5.元件可以選擇把它的 state 作為 props 向下傳遞到它的子元件中:
<FormattedDate date={this.state.date} />
“自上而下”或是“單向”的資料流。任何的 state 總是所屬於特定的元件,而且從該 state 派生的任何資料或 UI 只能影響樹中“低於”它們的元件
事件處理
React 元素的事件處理和 DOM 元素的很相似,但
- react事件的命名採用駝峰命名式,
- 使用 JSX 語法時需要傳入一個函式作為事件處理函式,而不是一個字串。
HTML:
<button onclick="activateLasers()">
Activate Lasers
</button>
React:
<button onClick={activateLasers}>
Activate Lasers
</button>
- 不能通過返回false的方式阻止預設行為,必須顯式的使用preventDefault()
比如阻止連結預設開啟一個新頁面
HTML
<a href="#" onclick="console.log('The link was clicked.'); return false">
Click me
</a>
React:
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
使用ES6 類 定義一個元件時,通常的做法是將事件處理函式宣告為 class 中的方法。
例如:Toggle元件,渲染一個讓使用者切換開關狀態的按鈕。
class Toggle extends React.component{
constructor(props){
super(props);
this.state={ isToggleOn: true };
this.handleClick=this.handleClick.bind(this);
}
handleClick(){
this.setState((state)=>{
isToggleOn:!state.isToggleOn
});
}
render(){
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn?'On':'Off'}
</button>
);
}
}
ReactDom.render(
<Toggle />,
document.getElementById('root')
);
【通常情況下,如果你沒有在方法後面新增(),
你應該為這個方法繫結this
。或用箭頭函式,但是不推薦使用,因為每次渲染元件都會建立不同的回撥函式,而且如果該回調函式作為props傳入子元件,這些元件可能進行額外的重新渲染】
向事件處理函式傳遞引數
1.箭頭函式
2.Function.prototype.bind()
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
條件渲染
在 React 中,可以建立不同的元件來封裝各種需要的行為。依據應用的不同狀態,可以只渲染對應狀態下的部分內容。