React (Class component)
環境建置
webpack
install
1 | mkdir react-self-app |
webpack config
1 | // ./webpack.config.js |
add file
./index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html lang="en">
<!-- ./index.html -->
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello</title>
</head>
<body>
hello
<!-- add webpack generate file -->
<script src="./dist/bundle.js"></script>
</body>
</html>./src/index.js
1
2
3// ./src/index.js
import { log } from "./utils";
log("hello world");./src/utils.js
1
2
3
4// ./src/utils.js
export function log(str) {
console.log(str);
}
add webpack script
package.json
1 | { |
run webpack script
1 | npm run start |
load index.html from browser
console show -> hello world
babel
install babel
1 | # babel-loader use by webpack |
babel config
.babelrc
1
2
3
4
5// .babelrc
{
// set babel transfer condition
"presets": ["@babel/preset-env"]
}./webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25// ./webpack.config.js
const path = require("path");
module.exports = {
// source file
entry: "./src/index.js",
output: {
// output path
path: path.join(__dirname, "/dist"),
// output file name
filename: "bundle.js",
},
module: {
rules: [
// 用 babel-loade 打包所有 .js 檔案,排除目錄 node_modules
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
],
},
};
change file
- ./src/index.js
1
2
3
4
5
6
7// ./src/index.js
import { log } from "./utils";
const obj = {
text: "hello world!!!",
};
const { text } = obj;
log(text);
run webpack script
1 | npm run start |
load index.html from browser
console show -> hello world!!!
react
install
1 | yarn add react react-dom @babel/preset-react |
config
1 | // .babelrc |
add file for react
./index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html lang="en">
<!-- ./index.html -->
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello</title>
</head>
<body>
<!-- add for react -->
<div id="root"></div>
<!-- add webpack generate file -->
<script src="./dist/bundle.js"></script>
</body>
</html>./src/index.js
1
2
3
4
5
6// ./src/index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
// App render to root
ReactDOM.render(<App />, document.getElementById("root"));./src/App.js
1
2
3
4
5
6
7
8
9
10// ./src/App.js
import React, { Component } from "react";
class App extends Component {
render() {
return <h1>Hello React</h1>;
}
}
export default App;
run webpack script
1 | npm run start |
load index.html from browser
browser show -> Hello React
setup webpack dev derver
change bundle.js add hash
1 | // ./webpack.config.js |
install html-webpack-plugin
1 | yarn add html-webpack-plugin |
./webpack.config.js add html-webpack-plugin
1 | // ./webpack.config.js |
./index.html remove <script src=”./dist/bundle.js”> </script>
1 |
|
run webpack script
1 | npm run start |
load ./dist/index.html from browser
browser show -> Hello React
install webpack dev server
1 | yarn add webpack-dev-server |
change webpack script
package.json
1 | { |
run webpack script
1 | npm run start |
基礎
Component
1 | // ./src/App.js |
Event
1 | // ./src/App.js |
State
使用 on click function #1
1 | // ./src/App.js |
使用 on click function #2
1 | // ./src/App.js |
使用 箭頭函數 example
- 箭頭函數 的 this, 為呼叫時之 this
1 | // ./src/App.js |
this 值,取決於如何被呼叫
1 | // ./src/App.js |
props and event 溝通
1 | // ./src/App.js |
載入 CSS
install
1 | npm install style-loader css-loader |
modify ./webpack.config.js
1 | // ./webpack.config.js |
import css
1 | // ./src/App.js |
add css
1 | /* ./style.css */ |
styleds-components
install
1 | npm install styled-components |
use styled-components
1 | // ./src/App.js |
Ref
Ref 是藉由使用 React.createRef() 所產生的,它藉由 ref 參數被依附在 React element。Ref 常常會在一個 component 被建立出來的時候,被賦值在某個 instance 屬性,這樣一來他們就可以在整個 component 裡面被參考。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30import React from "react";
export default class APP extends React.Component {
constructor(props) {
super(props);
// 產生一個可以儲存 textInput DOM element 的 ref
this.textInput = React.createRef();
this.focusTextInput = this.focusTextInput.bind(this);
}
focusTextInput() {
// 特別利用原生的 DOM API 來關注文字的輸入
// 注意:我們正利用「current」來取得 DOM 節點
this.textInput.current.focus();
}
render() {
// 告訴 React 我們想要將 <input> ref
// 和我們在 constructor 產生的 `textInput` 連結
return (
<div>
<input type="text" ref={this.textInput} />
<input
type="button"
value="Focus the text input"
onClick={this.focusTextInput}
/>
</div>
);
}
}你不能在 function component 上使用 ref,因為他們沒有 instance。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function MyFunctionComponent() {
return <input />;
}
class Parent extends React.Component {
constructor(props) {
super(props);
this.textInput = React.createRef();
}
render() {
// This will *not* work!
return (
<MyFunctionComponent ref={this.textInput} />
);
}
}
React 的生命週期
![pic1](/2021/10/26/react-6/pic1.jpg)
進階
input 共用 onChnage
1 | var Hello = React.createClass({ |
練習
Form 報名表單
./style.css */
1
2
3
4
5/* ./style.css */
.App {
margin: 10px auto;
width: 300px;
}./src/App.js - form
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173// ./src/App.js - form
import React, { Component } from "react";
import "./style.css";
function CheckBox({ value, id, label, checked, onChange }) {
return (
<span>
<input
id={id}
type="checkbox"
value={value}
name="time"
checked={checked}
onChange={onChange}
/>
<label htmlFor={id}>{label}</label>
</span>
);
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
name: "123",
address: "sdsd",
review: "ds",
gender: "female",
city: "taipei",
time: ["2"],
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handelInputChange = this.handelInputChange.bind(this);
this.handleCheckboxChange = this.handleCheckboxChange.bind(this);
}
handleSubmit(e) {
e.preventDefault();
console.log(this.state);
}
handelInputChange(e) {
console.log(e.target.value);
console.log(e.target);
this.setState({ [e.target.name]: e.target.value });
}
handleCheckboxChange(e) {
const { time } = this.state;
const value = e.target.value;
const newTime = time.filter((item) => item !== value);
this.setState({
time: newTime.length != time.length ? newTime : [...time, value],
});
}
// onBlur 離開表單
handleVerify(e) {
console.log("onBlur name:", e.target.name);
}
render() {
const { name, address, review, gender, city, time } = this.state;
return (
<div className="App">
<form onSubmit={this.handleSubmit}>
<div>
姓名 :{" "}
<input
name="name"
type="text"
value={name}
onChange={this.handelInputChange}
onBlur={this.handleVerify}
/>
</div>
<div>
地址 :{" "}
<input
name="address"
type="text"
value={address}
onChange={this.handelInputChange}
onBlur={this.handleVerify}
/>
</div>
<div>
心得 :{" "}
<textarea
name="review"
value={review}
onChange={this.handelInputChange}
onBlur={this.handleVerify}
/>
</div>
<div>
性別:
<input
id="gender_male"
checked={gender === "male"}
type="radio"
value="male"
name="gender"
onChange={this.handelInputChange}
/>
<label htmlFor="gender_male">男</label>
<input
id="gender_female"
checked={gender === "female"}
type="radio"
value="female"
name="gender"
onChange={this.handelInputChange}
/>
<label htmlFor="gender_female">女</label>
<input
id="gender_other"
checked={gender === "other"}
type="radio"
value="other"
name="gender"
onChange={this.handelInputChange}
/>
<label htmlFor="gender_other">其他</label>
</div>
<div>
縣市:
<select
name="city"
value={city}
onChange={this.handelInputChange}
onBlur={this.handleVerify}
>
<option value="taipei">台北市</option>
<option value="new_taipei">新北市</option>
<option value="other">其他</option>
</select>
</div>
<div>
有空時間:
<CheckBox
value="1"
id="week_1"
checked={time.indexOf("1") >= 0}
label="星期一"
onChange={this.handleCheckboxChange}
/>
<CheckBox
value="2"
id="week_2"
checked={time.indexOf("2") >= 0}
label="星期二"
onChange={this.handleCheckboxChange}
/>
<CheckBox
value="3"
id="week_3"
checked={time.indexOf("3") >= 0}
label="星期三"
onChange={this.handleCheckboxChange}
/>
</div>
<div>
<input type="submit" />
</div>
</form>
</div>
);
}
}
export default App;