插值表达式 {}
在插值表达式中,可以使用js与jsx语法混用.
1
2
3
4
5
6
7
8
9// write your code here
const JSX = <div>
<h1>{'h1'}</h1>
<p>{'p'}</p>
<ul>{ [1, 2, 3].map(item => {
return <li>{item}</li>
})}
</ul>
</div>;jsx注释 {/* */}
渲染 HTML 元素为 DOM 树
使用reactRender(jsx组件, dom节点)
1 | ReactDOM.render(JSX, document.getElementById('challenge-node')) |
react定义Html中的class属性, 不可以使用class, 只能使用className(class在js中为关键字)
jsx中, 都存在自闭合标签, 就是不需要关闭标签 类似
1
<br />
好了, 在jsx语法中,也只能有一个父级标签
无状态组件
1
2
3
4
5const mycomponent = () => {
return (
<div>some</div>
)
}基于class语法创建一个 React 组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyComponent extends React.Component {
constructor(props) {
// 这个东西很关键
super(props);
}
render() {
// change code below this line
return (
<h1>Hi</h1>
);
// change code above this line
}
};用组合的方式创建一个 React 组件: z(x) = f(g(x))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23const child = () => {
return (
<div>
{ 'Hello child.' }
</div>
)
}
class MyComponent extends React.Component {
constructor(props) {
// 这个东西很关键
super(props);
}
render() {
// change code below this line
return (
<div>
<child></child>
</div>
);
// change code above this line
}
};React 渲染嵌套组件
没啥,也就组件嵌套组件.渲染 class 组件为 Dom 树
1 | ReactDOM.render(<componentName>, document.getElementById('challenge-node')) |
props传递
1
2
3<App>
<Welcome user={如果是变量的化} />
</App>默认的props-defaultProps
1
2
3
4
5
6
7
8
9
10
11const ShoppingCart = (props) => {
return (
<div>
<h1>Shopping Cart Component{props.items}</h1>
</div>
)
};
// change code below this line
ShoppingCart.defaultProps = {
items: 0
}React:使用 PropTypes 来定义你期望的 Props // 限制props的类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14// 使用 PropTypes
const Items = (props) => {
return <h1>Current Quantity of Items in Cart: {props.quantity}</h1>
};
// change code below this line
Items.propTypes = {
quantity: PropTypes.number.isRequired
}
// change code above this line
Items.defaultProps = {
quantity: 0
};访问props
状态组件使用this关键字: this.props
无状态组件使用入参props创建带自身状态的组件: state
1 | class StatefulComponent extends React.Component { |
在render函数的return语句前可以放任意的js, 那么意味着我们可以在渲染之前, 对state进行处理.
原则: 改变组件状态必须要使用 this.setState
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'Initial State'
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
// change code below this line
this.setState({
name: 'React Rocks!'
});
// change code above this line
}
render() {
return (
<div>
<button onClick={this.handleClick}>Click Me</button>
<h1>{this.state.name}</h1>
</div>
);
}
};在react组件里, 组件里的方法是访问不到组件的this的, 这个时候就要我们手动去修复这个问题
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
26class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
itemCount: 0
};
// change code below this line
this.addItem = this.addItem.bind(this)
// change code above this line
}
addItem() {
this.setState({
itemCount: this.state.itemCount + 1
});
}
render() {
return (
<div>
{ /* change code below this line */ }
<button onClick={this.addItem}>Click Me</button>
{ /* change code above this line */ }
<h1>Current Item Count: {this.state.itemCount}</h1>
</div>
);
}
};input框数据双向绑定(万年问题)
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
29class ControlledInput extends React.Component {
constructor(props) {
super(props);
this.state = {
input: 'xxx'
};
// change code below this line
this.assignText = this.assignText.bind(this)
// change code above this line
}
// change code below this line
assignText(e) {
this.setState({
input: e.target.value
})
}
// change code above this line
render() {
return (
<div>
{ /* change code below this line */}
<input type='text' value={this.state.input} onChange={this.assignText}/>
{ /* change code above this line */}
<h4>Controlled Input:</h4>
<p>{this.state.input}</p>
</div>
);
}
};将 State 作为 Props 传递给子组件—-父子数据传递
遵循两个原则:
- 单向数据流
- 最小状态组件原则
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// 父子数据传递
class MyApp extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'CamperBot'
}
}
render() {
return (
<div>
<Navbar name={this.state.name} />
</div>
);
}
};
class Navbar extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h1>Hello, my name is: {this.props.name} </h1>
</div>
);
}
};
父级向子集传递的不只是state, 也可以是function
传递function的原因是, 给子组件一个修改state的机会.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
57class MyApp extends React.Component {
constructor(props) {
super(props);
this.state = {
inputValue: ''
}
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({
inputValue: event.target.value
});
}
render() {
return (
<div>
{ /* change code below this line */ }
{this.state.inputValue}
<GetInput input={this.state.inputValue} handleChange={this.handleChange}/>
<RenderInput input={this.state.inputValue} />
{ /* change code above this line */ }
</div>
);
}
};
class GetInput extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h3>Get Input:</h3>
<input
value={this.props.input}
onChange={this.props.handleChange}/>
</div>
);
}
};
class RenderInput extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h3>Input Render:</h3>
<p>{this.props.input}</p>
</div>
);
}
};使用生命周期方法Overview
1
2
3
4
5
6
7
8
9
10
11
12
13
14componentWillMount()
// 即将挂载
componentDidMount()
// 挂载后
componentWillReceiveProps()
// 将要接收props
shouldComponentUpdate()
// 组件更新
componentWillUpdate()
// 组件即将更新
componentDidUpdate()
// 组件更新后
componentWillUnmount()
// 组件卸载componentDidMount — 组件装载到 DOM 后会调用
这个生命周期:
- 一般是放数据请求.请求后把数据放入模板, 再进行渲染.类似我们vue会把请求初始化放到created()
- 挂载浏览器事件(特指全局的哦, 比如按回车然后, 执行某些搜索, 我们在componentDidMount周期里挂载, 在componentWillUnmount里卸载这个事件)
componentWillReceiveProps — 组件接收到props或者props更新就会触发: 入参默认为该次传入的props
componentDidUpdate — 组件再次重新渲染会触发: 入参默认为该次传入的props
componentWillMount/componentDidMount — 首次渲染, 首次卸载会触发
shouldComponentUpdate — 该生命周期控制组件是否需要更新, 入参默认为nextProps, nextState, 出参必须要一个boolean值, 告诉react是否需要更新该组件,因为, react的行为是, 如果传入了props那么无论怎样都会去更新组件, 触发渲染.(这个生命周期是作为一个优化提出的)
react中的内联样式
在react使用样式的方式有两种
- 正常导入
- 使用内联样式要点: 1. style中只接受对象 2. 不识别连字符, 要使用驼峰命名
1
<div style={{color: "yellow", fontSize: 16}}>Mellow Yellow</div>
- React:在 React Render 方法中使用 JavaScript
在render函数的return语句之前,我们可以使用任意的js
使用 If/Else 条件进行渲染
记住, 这种判断一般都抽离出来成为一个逻辑,不要再jsx中写入太多逻辑.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
29class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
display: true
}
this.toggleDisplay = this.toggleDisplay.bind(this);
}
toggleDisplay() {
this.setState({
display: !this.state.display
});
}
render() {
// change code below this line
let content
if(this.state.toggleDisplay) {
content = <h1>Hello</h1>
} else {
content = ''
}
return (
<div>
<button onClick={this.toggleDisplay}>Toggle Display</button>
{content}
</div>
);
}
};使用 && 获得更简洁的条件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
display: true
}
this.toggleDisplay = this.toggleDisplay.bind(this);
}
toggleDisplay() {
this.setState({
display: !this.state.display
});
}
render() {
// change code below this line
return (
<div>
<button onClick={this.toggleDisplay}>Toggle Display</button>
{this.state.display && <h1>markup</h1>}
</div>
);
}
};使用三元表达式进行条件渲染
1
2
3
4
5const buttonOne = <button onClick={this.submit}>Submit</button>;
const buttonTwo = <button>You May Enter</button>;
const buttonThree = <button>You Shall Not Pass</button>;
this.state.input === '' ? buttonOne : (this.state.userAge >= 18 ? buttonTwo : buttonThree)服务端渲染(待续)
完结撒花