-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreact.note
380 lines (294 loc) · 10.9 KB
/
react.note
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
React:
用于构建用户界面的JavaScript库,是MVC(model-view-control)的V层框架,专注于视图层
angular 谷歌 粘性很强 ,强主张 TS-typeScript,脏值检查
react facebook 虚拟DOM,让开发者专注于数据处理,并且根据数据的变化去操作DOM(性能优化的去操作),生态(手机端)
React 特点
1.声明式设计 −React采用声明范式,可以轻松描述应用。
2.高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
3.灵活 −React可以与已知的库或框架很好地配合。
4.JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
5.组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
6.单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
React的安装:
my-app:自定义文件名
或者用yarn start
ReactDom.render()有三个参数:
JSX:js xml可扩展的js语言
class必须写成className
标签必须是闭合状态 包括单标签 <input />
{}
可以执行js语句
如果花括号内部有数组,默认展开
如果元素属性是一个变量需要花括号 src={obj.xx}
受控组件、非受控组件
事件
onClick、onChange、onKeyUp、onMouseOver...
事件函数的this默认为undefined,所以要使用bind(this)修正this指向
如果适合create-react-app 有语法不用使用bind
创建组件
类创建:(建议采用)
class 组件名称(首字母大写) extends React.Component{
render(){
return (
JSX -> 结构
)
}
}
函数创建:(注意this)
function App(){
return (
<div>
<div>别的上面东西</div>
</div>
)
}
状态 state:
this.setState(参数,参数):
异步执行
第一个参数可以是对象也可以是函数
参数为函数:函数的第一个参数为没有改变的state,第二个参数为props,如果要改变状态需要 return 一个*对象*
this.setState((prev,props)=>({
num:this.state.num+1
}))
setState放在
定时器中执行时会出现同步
componentDidMount(原生事件)中执行也是同步
所以this.setState可以时同步也是异步
第二个参数:状态改变之后的回调
constructor(){
super();
this.state = {
数据
}
}
修改数据
this.setState({新数据}) //参数可以是对象也可以是函数
受控组件:
如果在表单元素上设置了一个(value、checked)默认值,那么该元素就变成了受控组件
非受控组件:
不设置默认值
defaultValue
父子组件传递:
在父组件上给子组件中绑定自定义属性,把数据放到自定义属性上(发送)
在子组件中使用this.props.自定义属性名去接收(接收)
index.js文件:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import List from './components/list'
if (module.hot) {
module.hot.accept();
}
class App extends Component { //App为父组件
constructor() {
super();
this.state = {
arr: [{name:'tom'}, {name:'lili'}]
}
}
render() {
let { arr } = this.state;
let list = arr.map((item, i) => {
return (
<List
// text={item}
// key={i}
//建议使用如下方式,便于管理,可读性强
{...{
text: item.name,
key: i,
a: 10,
b: 20
}}
/>
)
});
//结构
//在父组件中给子组件中绑定自定义属性,把父组件的数据放到子组件中的自定义属性上(发送)
return (
<ul>
{/* <List data={this.state.arr} /> */}
{list}
</ul>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'))
list.js文件,为App的子组件
import React, { Component } from 'react';
class list extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
//在子组件中使用this.props.自定义属性名去接收数据
//console.log(this.props.data)
let { a, b } = this.props;
console.log(a, b);
console.log(this.props)
console.log(this.props.text)
return (
<li>{this.props.text}</li>
);
}
}
export default list;
父级的单向流动
父级的数据传到子级,数据本身还是父级的,如果用户操作子级要改变传递的数据,那么不能子级改,要让父级改-----单向流动;
也就是说,父级要定义一个修改数据的方法,在传递数据的时候,方法也一起传递个子级;
当触发子级行为的时候,子级去调用父级修改数据的方法,然后父级收到了子级的修改,父级修改数据,当父级的数据发生变化的时候,又把最新的数据传递给了子级。
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class App extends Component {
constructor(props) {
super(props);
this.state = {
num: 0
}
}
//父级改变数据的方法
add = () => {
console.log(this)
let { num } = this.state;
num++;
this.setState({ num })
}
render() {
let { num } = this.state;
console.log(num);
return (
<div>
<div>父级的{num}</div>
{console.log(num)}
<hr />
{/*在父组件上给子组件中绑定自定义属性num add,把数据放到自定义属性上(发送) */}
<Btn num={num} add={this.add} />
{/* <button onClick={this.add}>0</button> */}
</div>
);
}
}
class Btn extends Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
//子级接收父级传递的数据和方法
let { num, add } = this.props;
//console.log(num,add)
return (
//需要传参的时候可使用箭头函数
<button onClick={add}>
{num}
</button>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'))
第二种情况:父级把数据给了子级,只想在触发子级的时候,子级的数据变化,父级的数据不变;
也就是说,父级通过自定义的方式传递数据给子级,子级可以在constructor中接收到父级传递的数据(就一次),把父级传递的这个数据,变为this.state,子级就拥有了父级的数据,并且修改子级的数据不会影响父级。
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class App extends Component {
constructor(props) {
super(props);
this.state = {
num: 0
}
}
//父级改变数据的方法
/**
* num:子级传过来的参数,用于改变子级时候父级跟着改
*/
change = (num) => {
num %= 2;//父级只有0、1,不都跟着子级走
this.setState({ num })
}
render() {
let { num } = this.state;
console.log(num);
return (
<div>
<div>父级的{num}</div>
{console.log(num)}
<hr />
{/*在父组件上给子组件中绑定自定义属性num add,把数据放到自定义属性上(发送) */}
<Btn num={num} change={this.change} />
</div>
);
}
}
/*
父级把数据给了子级,只想在触发子级的时候,子级的数据变化,父级的数据不变;
也就是说,父级通过自定义的方式传递数据给子级,子级可以在constructor中接收到父级传递的数据(就一次),把父级传递的这个数据,变为this.state,子级就拥有了父级的数据,并且修改子级的数据不会影响父级。
*/
class Btn extends Component {
constructor(props) {
super(props);
this.state = {
num: this.props.num
}
}
add = () => {
let { num } = this.state;
num++;
this.setState({ num });
this.props.change(num)
}
render() {
let { num } = this.state;
return (
<button onClick={this.add}>
{num}
</button>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'))
生命周期
一个组件从开始到死亡的过程中会触发该生命周期中的事件,把这个事件的生命周期函数暴露出来给我们使用,这个(些)函数就叫生命周期
mounting--初始化阶段(第一次)
constructor =>初始化数据
componentWillMount =>挂载之前
render 第一次渲染 时要处理的逻辑 (不要使用this.setState,否则会有死循环)
componentDidMount => 挂载之后 请求数据
updating--更新阶段
shouldComponetUpdate ==>性能优化
componentWillUpdate ==>更新之前
render ==>更新渲染 (不要使用this.setState,否则会有死循环)
componentDidUpdate ==>更新之后
注意:更新阶段中不要使用this.setState,否则会有死循环,可以在componentWillReceiveProps方法中使用
componentWillReceiveProps ==>父级数据发生变化时候触发
unmounting 阶段 ==>卸载或者跳路由时触发
componentWillUnmount 当组件死亡的时候触发(卸载,跳路由,关定时器,数据重置,变量置空、事件清除)
ref:快速定位组件或元素
可以快速的获取组件或者元素
在指定组件上写一个ref的属性,值就随意
<App ref="app"/> 定义好了
this.refs.app 就能获得这个组件
prop-types 验证传递数据的类型,目的(为了报错)
安装 npm i prop-types -S
引包 import PropType from 'prop-types';
路由 https://reacttraining.com/react-router/
安装 npm i react-router-dom -S
引包 import {BrowserRouter as Router |HashRouter as Router,Route} from 'react-router-dom'
路由有2种
一种是hash路由 #/home
另一种history路由 /home
使用
必须把Router放到根下
ReactDOM.render((
<Router>
<App />
</Router>
),document.getbyId('xx'))
function App (){
return (
<Route path="/" component={App}/>
)
}
切换路由的时候可以通过组件内的props获取到路由信息
history 就是与H5的history一样,能够操作浏览器的历史纪录
location 里面可以获取hash #、search?、state:{key:vakue}等
match 里面可以获取url、path