-
JSX - 使用 HTML 语法写的代码可以被转为 JS 对象
-
Virtual DOM - 实际 DOM 的 JS 描述,用于提升性能,操作实际的 DOM 很慢,平时多操作虚拟 DOM,只在必要的时候变动实际 DOM。
-
React.Component - 用于创建新组件
-
render(Method)- 描述组件的 UI 样式
-
ReactDOM.render - 把一个组件渲染到 DOM 节点
-
state - 组件内的数据存储对象
-
constructor - 构建组件的初始 state
-
setState - 用于更新组件的 state,并重新渲染 UI
-
props - 从父组件传递给子组件的数据
-
propTypes - 可以控制传给子组件的 props 的类型
-
defaultProps - 为组件设置默认 props
-
Component LifeCycle
- componentDidMount 组件被挂载后触发
- componentWillUnmount 组件被挂载前触发
- getDerivedStateFromProps 组件挂载和 props 变动时触发,用于当组件的 props 变动后更新组件的 state
-
Events
- onClick
- onSubmit
- onChange
import React from 'react'
import ReactDOM from 'react-dom'
class HelloWorld extends React.Component {
render() {
return (
<div>Hello World!</div>
)
}
}
ReactDOM.render(<HelloWorld />, document.getElementById('root'));
render()
是这个 class 中的唯一一个方法,每个组件都需要有一个 render()
,用于描述组件的 UI 界面。
ReactDOM.render
接收2个参数:
- 想要渲染的组件
- 想要在哪个 DOM 节点上渲染这个组件
render()
中的内容类似 HTML,叫做 “JSX”,可以把类似 HTML 的内容转为 JS 对象,react 可以使用这些 JS 对象与 “virtual DOM” 交互。
上面的 JSX 实际会被编译为:
class HelloWorld extends React.Component {
render() {
return React.createElement("div", null, "Hello World");
}
}
用户事件改变 state -> 重新渲染虚拟DOM -> 比较新旧虚拟DOM -> 更新实际DOM中的必要部分
现在已经了解到的概念:
- JSX
- Virtual DOM
- React.Component
- render (method)
- ReactDOM.render
最好可以描述出来他们的概念作用。
每个组件都可以管理自己的 state,并可以传递给子组件。
假设有一个用户组件,管理着用户信息,有另一个组件也需要用户信息,但他不是用户组件的子组件,那么需要创建一个新组件,作为用户组件和此组件的父组件。父组件可以通过 props 向下传递 state。
class HelloUser extends React.Component {
constructor(props) {
super(props)
this.state = {
username: 'tylermcginnis'
}
}
render() {
return (
<div>
Hello {this.state.username}
</div>
)
}
}
这里使用了 constructor
,用于设置组件的 state,其中任何放到 this.state
中的数据都会成为组件 state 的一部分。
改变数据 -> 重绘虚拟DOM -> 比较新旧虚拟DOM -> 更新实际DOM中的必要部分
setState
就是用于“改变数据”。
只要 setState
被调用,虚拟DOM就会重新渲染。
class HelloUser extends React.Component {
constructor(props) {
super(props)
this.state = {
username: 'tylermcginnis'
}
this.handleChange = this.handleChange.bind(this)
}
handleChange (e) {
this.setState({
username: e.target.value
})
}
render() {
return (
<div>
Hello {this.state.username} <br />
Change Name:
<input
type="text"
value={this.state.username}
onChange={this.handleChange}
/>
</div>
)
}
}
handleChange
每次用户输入时都会被调用,handleChange 调用 setState 修改 username。
setState 会改变虚拟DOM,从而改变实际DOM。
onChange 会在每次 input 的值变化时调用绑定的方法。
这个示例的流程:
用户在 input 中输入 -> handleChange 被调用 -> setState 修改组件的 state -> 重新渲染虚拟dom -> 比较 -> 更新实际DOM
现在已经了解到的概念:
- JSX
- Virtual DOM
- React.Component
- render (method)
- ReactDOM.render
- state
- constructor
- setState
props 用于向子组件传递数据,在最高层父组件中管理数据,如果子组件需要,就可以通过 props 向下传递。
props 示例:
import React from 'react';
import ReactDOM from 'react-dom';
class HelloUser extends React.Component {
render() {
return (
<div> Hello, {this.props.name}</div>
)
}
}
ReactDOM.render(<HelloUser name="Tyler" />, document.getElementById('root'));
父子组件示例:
class FriendsContainer extends React.Component {
constructor(props) {
super(props)
this.state = {
name: 'Tyler McGinnis',
friends: ['Jake Lingwall', 'Sarah Drasner', 'Merrick Christensen']
}
}
render() {
return (
<div>
<h3> Name: {this.state.name} </h3>
<ShowList names={this.state.friends} />
</div>
)
}
}
设置了初始的 state,把部分数据传递给了子组件。
class ShowList extends React.Component {
render() {
return (
<div>
<h3> Friends </h3>
<ul>
{this.props.names.map((friend) => <li>{friend}</li>)}
</ul>
</div>
)
}
}
this.props.names.map
是 Array.prototype.map
,map 会创建一个新的数组,对数组中的每个元素调用 callback 方法,并使用返回值填充数组。
例如:
const friends = ['Jake Lingwall', 'Sarah Drasner', 'Merrick Christensen'];
const listItems = friends.map((friend) => {
return "<li> " + friend + "</li>";
});
// 结果
// ["<li> Jake Lingwall</li>", "<li> Sarah Drasner</li>", "<li> Merrick Christensen</li>"];
记住:哪里的数据,就应该在哪里操作。如果需要在外部操作,应该把 getter/setter 传递过去。
class FriendsContainer extends React.Component {
constructor(props) {
super(props)
this.state = {
name: 'Tyler McGinnis',
friends: [
'Jake Lingwall',
'Sarah Drasner',
'Merrick Christensen'
],
}
this.addFriend = this.addFriend.bind(this)
}
addFriend(friend) {
this.setState((state) => ({
friends: state.friends.concat([friend])
}))
}
render() {
return (
<div>
<h3> Name: {this.state.name} </h3>
<AddFriend addNew={this.addFriend} />
<ShowList names={this.state.friends} />
</div>
)
}
}
prop-types 用于描述 props,例如 类型、是否必须。
import React from 'react'
import PropTypes from 'prop-types'
class AddFriend extends React.Component {
constructor(props) {
super(props)
this.state = {
newFriend: ''
}
}
updateNewFriend(e) {
this.setState({
newFriend: e.target.value
})
}
handleAddNew() {
this.props.addNew(this.state.newFriend)
this.setState({
newFriend: ''
})
}
render() {
return (
<div>
<input type="text" value={this.state.newFriend} onChange={this.updateNewFriend} />
<button onClick={this.handleAddNew}> Add Friend </button>
</div>
)
}
}
AddFriend.propTypes: {
addNew: PropTypes.func.isRequired
}
defaultProps 用于指定 props 的默认值
class ShowList extends React.Component {
render() {
return (
<div>
<h3> Friends </h3>
<ul>
{this.props.names.map((friend) => {
return <li> {friend} </li>
})}
</ul>
</div>
)
}
}
ShowList.defaultProps = {
names: []
}
现在已经了解到的概念:
- JSX
- Virtual DOM
- React.Component
- render (method)
- ReactDOM.render
- state
- constructor
- setState
- props
- prop-types
- defaultProps
- events
如果想请求初始化数据,在哪儿做?props 变动的时候做一些逻辑处理,在哪儿做?这就涉及组件的生命周期。
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
name: 'Tyler McGinnis'
}
}
componentDidMount(){
// 组件挂载到DOM后触发
// 适合发起 AJAX requests
}
static getDerivedStateFromProps(nextProps, prevState) {
// 从该函数返回的对象将与当前状态合并.
}
componentWillUnmount(){
// 组件被挂载前触发
// 适合清理 listeners
}
render() {
return (
<div>
Hello, {this.state.name}
</div>
)
}
}
参考 https://tylermcginnis.com/reactjs-tutorial-a-comprehensive-guide-to-building-apps-with-react/
网友评论