React 組件(Component) 三大重點:屬性(props)、狀態(state)、生命週期(lifecycle)

https://annie101101046.github.io/React-practice/

Recap:React Element 分成兩種

基本的 HTML DOM Element (如在:H1 標籤裡包東西)

React 組件(Component) → 自訂的 React Element


一個 React Component 的組成

一個 React Component 除了有重要的繪製 render( ) 外,還會有屬性(props)跟 狀態(state)。

React Component 組件的屬性:props

建立組件實體時,設定屬性物件(可以給 null):

React.createElement(
組件類別名稱,[屬性物件],[子元件]
);

在組件的方法中使用屬性物件:

class 組件類別名稱 extends React.Component{
render(){
// 使用 this.props 取得物件屬性
this.props;
}
}

範例使用:

class MyHead extends React.Component {
render() {
//在上面可以直接用 this.props 讀出屬性值
// console.log(this.props.level)
return React.createElement(“H” + this.props.level, null, “Hello Component”);
 }
}
window.addEventListener(“load”, () => {

// 1.建立自訂的 React 組件實體屬性
let myComponent = React.createElement(MyHead, {
level: 3
});

// 2. 將建立好的組件放到容器中
ReactDOM.render(myComponent, document.body);
});

 

巢狀組件結構:建立組件實體時,設定子元件

React.createElement(
組件類別名稱,[屬性物件],[子元件]
);

//子元件可以是其他的組件實體

//就跟我們在 HTML 一樣,可以在 tag 裡面放其他的 tag

步驟 → 在 document.body 中,有 MyHeadList ,裡面有 5 個 MyHead 組件:

// 設計新的組件
class MyHeadList extends React.Component {
render() {

// 把 5 個 MyHead 放進來,用陣列處理
let heads = [];
let head;
for (let i = 1; i < 6; i++) {
//產生 MyHead 物件,屬性設定成 i
head = React.createElement(MyHead, {
level: i
});

//做出來放進陣列
heads.push(head);
}

// 不用特別設定屬性,但要設定子元件(heads 是個一陣列)
return React.createElement(“DIV”, null, heads);
}

}

主程式中繪製 MyHeadList,不用額外屬性:

window.addEventListener(“load”, () => {
// 1.建立自訂的 React 組件實體
let myComponent = React.createElement(MyHeadList, null);

// 2. 將建立好的組件放到容器中
ReactDOM.render(myComponent, document.body);
});

網頁載入後,產生一個 React component 組件叫做 myComponent (其實就是 MyHeadList 這個組件,組建的上層),畫到 body 上

MyHeadList 裡有一個子元件 heads ,而 heads 其實就是 5 個 MyHead,有 level 1–4 的屬性


組件(Component)的狀態(state)

→ 預期未來會變動的設定(希望畫面會重新繪製)

組件類別的建構式:

class 組件類別名稱 extends React.Component{
constructor(props){
//一定要先呼叫父類別的建構式
//一定要傳屬性的參數進去
super(props);
}
}
//如果都沒寫,就會用 React.Component 裡面的建構式來

組件類別的建構式中,初始化狀態:

class 組件類別名稱 extends React.Component{
constructor(props){
super(props);
this.state={}; //初始化狀態為空白物件或者初始化狀態物件 this.state={data:10};
}
}

更新狀態: setState(新的組件狀態);

更新組件狀態:

Class 組件類別名稱 extends React.Component{
//update()隨性建立的測試用方法
update(){

// 使用 setState(狀態物件)來更新狀態
this.setState({data:”新的資料”});

//禁止直接更新狀態物件 —> this.state={data:”新的資料”}
}
}

當更新狀態與目前的狀態有關聯:setState((目前狀態, 目前屬性))=>(新的狀態));

//要用箭頭函示,把兩個參數丟進去,得到一個新的回傳值

setState((目前狀態, 目前屬性))=>(新的狀態));
//要用箭頭函示,把兩個參數丟進去,得到一個新的回傳值

測試 code
Class 組件類別名稱 extends React.Component{
//update()隨性建立的測試用方法
update(){
// 新狀態資料 = 目前狀態資料 + 1
this.setState((currentState, currentProps)=>(
{data:currentState.data+1}
));
}
}
//更新狀態會自動呼叫 render() 重繪畫面

1.實際示範:一般的組件類別的建構式

class MyHead extends React.Component {
render() {
// console.log(this.props.level)
return React.createElement("H" + this.props.level, null, "崩╰(〒皿〒)╯潰");
}
}

// 設計新的組件
class MyHeadList extends React.Component {
//為 MyHead 建立一個建構式,給他狀態
constructor(props) {

//建構式接受外部傳的屬性當參數,一定要先呼叫父類別的建構式
//一定要傳屬性的參數進去

super(props);

//初始化狀態
this.state = {
maxLevel: 6
};

window.setTimeout(() => {
// 2 秒後執行程式碼
this.setState({
maxLevel: 3
});
}, 2000);

//當前 state 與等等的有關聯
// this.setState((currentState, currentProps) => ({
//     maxLevel: currentState.maxLevel + 1
// }));
// }, 2000);
}

render() {
// 把 5 個 MyHead 放進來,用陣列處理
let heads = [];
let head;

//i 利用 state 動態調整
for (let i = 1; i
//產生 MyHead 物件,屬性設定成 i
head = React.createElement(MyHead, {
level: i
});

//做出來放進陣列
heads.push(head);
}
return React.createElement("DIV", null, heads);
}
}
window.addEventListener("load", () => {
// 1.建立自訂的 React 組件實體
let myComponent = React.createElement(MyHeadList, null);

// 2. 將建立好的組件華道容器中
ReactDOM.render(myComponent, document.body);
});

2.實際示範:當更新狀態與目前狀態有關聯的建構式

class MyHead extends React.Component {
render() {
// console.log(this.props.level)
return React.createElement("H" + this.props.level, null, "崩╰(〒皿〒)╯潰");
}
}
// 設計新的組件
class MyHeadList extends React.Component {

//為 MyHead 建立一個建構式,給他狀態
constructor(props) {

//建構式接受外部傳的屬性當參數,一定要先呼叫父類別的建構式
//一定要傳屬性的參數進去

super(props);

//初始化狀態
this.state = {
maxLevel: 6
};

window.setTimeout(() => {

//     // 2 秒後執行程式碼
//     this.setState({
//         maxLevel: 3
//     });
// }, 2000);
//當前 state 與等等的有關聯

this.setState((currentState, currentProps) => ({
maxLevel: currentState.maxLevel + 1
}));
}, 2000);
}
render() {
// 把 5 個 MyHead 放進來,用陣列處理
let heads = [];
let head;
//i 利用 state 動態調整
for (let i = 1; i
//產生 MyHead 物件,屬性設定成 i
head = React.createElement(MyHead, {
level: i
});

//做出來放進陣列
heads.push(head);
}
return React.createElement("DIV", null, heads);
}
}
window.addEventListener("load", () => {

// 1.建立自訂的 React 組件實體
let myComponent = React.createElement(MyHeadList, null);

// 2. 將建立好的組件華道容器中
ReactDOM.render(myComponent, document.body);
});

 

組件の生命週期(lifecycle)

組件的重要操作 → 都定義在 React.Component 組件的父類別中,可以複寫

1.建立組件

2.更新組件

3.刪除組件

*建立組件:

constructor();

componentWillMount(); //react 正要把組件放到畫面上

render(); //主要組件繪製的邏輯

componentDidMount(); //確認組件已畫上去

*更新組件:

1.componentWillUpdate(); //將要更新

2.render(); // 更新的主要繪製邏輯寫這

3.componentDidUpdate(); //確認更新 *刪除組件:

componentWillUnmount(); // 刪除前

在組件類別中複寫方法,自訂邏輯

假設要讓畫面都不要停下來:

constructor(props) {
//建構式接受外部傳的屬性當參數,一定要先呼叫父類別的建構式
//一定要傳屬性的參數進去
super(props);

//初始化狀態
this.state = {

maxLevel: 1

};

//設定排程最好的時機在初始化後

componentWillMount() { //組件將要繪製前的時刻

window.setInterval(() => {

//每秒鐘執行這裡的邏輯

this.setState((currentState, currentProps) => {

return {maxLevel:currentState.maxLevel+1};

});

}, 1000);

}

假設要讓畫面停下來:

componentWillMount() { //組件將要繪製前的時刻

//設定一個排成 id => this.intervalId

this.intervalId = window.setInterval(() => {

//每秒鐘執行這裡的邏輯

this.setState((currentState, currentProps) => {

if (currentState.maxLevel > 6) {

//不要更新還是要 return

return currentState;

} else { //maxLevel + 1

return {

maxLevel: currentState.maxLevel + 1

};

}

});

}, 1000);

}

紀錄排程 id,必要時把排程清除:

//設定排程最好的時機在初始化後

componentWillMount() { //組件將要繪製前的時刻

//設定一個排成 id => this.intervalId

this.intervalId = window.setInterval(() => {

//每秒鐘執行這裡的邏輯

this.setState((currentState, currentProps) => {

if (currentState.maxLevel > currentProps.end) {

//不要更新還是要 return

return currentState;

} else { //maxLevel + 1

return {

maxLevel: currentState.maxLevel + 1

};
}

});

}, 1000);
}

componentWillUnmount() { //組建要刪除前的時刻

//把排程刪除

window.clearInterval(this.intervalId);

}

//不然網頁會不斷執行這個排程

邏輯是把組件的生命週期拿進來,所以會有 componentWillMount() 跟 componentWillUnmount(),主要邏輯是希望 component 每一秒更新,更新後因為 maxLevel 會加一,所以會畫出來,最多畫 6 個。

*MyHeadList 加入屬性(props)概念:讓 component 更有彈性決定要從哪裡畫到哪(code here:https://annie101101046.github.io/React-practice/

先往下找,增加屬性:
window.addEventListener("load", () => {

// 1.建立自訂的 React 組件實體

//在MyHeadList 可以給他一個屬性,讓他從哪跑到哪,這個 props 會傳到上方 MyHeadList 的 props

let myComponent = React.createElement(MyHeadList, {

start: 2,

end: 5

});

// 2. 將建立好的組件華道容器中

ReactDOM.render(myComponent, document.body);

});

往上找,把 maxLevel 都改成 props:

// 設計新的組件
class MyHeadList extends React.Component {

//為 MyHead 建立一個建構式,給他狀態
constructor(props) {

//建構式接受外部傳的屬性當參數,一定要先呼叫父類別的建構式
//一定要傳屬性的參數進去
super(props);

//初始化狀態

this.state = {

maxLevel: props.start //下方的 props

};

}

//設定排程最好的時機在初始化後

componentWillMount() { //組件將要繪製前的時刻

//設定一個排成 id => this.intervalId

this.intervalId = window.setInterval(() => {

//每秒鐘執行這裡的邏輯

this.setState((currentState, currentProps) => {

if (currentState.maxLevel > currentProps.end) {

//不要更新還是要 return

return currentState;

} else { //maxLevel + 1

return {

maxLevel: currentState.maxLevel + 1
};
}

});

}, 1000);
}