State Props——React的关键所在
只有 State,Props,仅此而已。
React 只有 State(状态)、Props(属性),仅此而已。就是这么简单。所以说,如果你会 JS,也了解了 State(状态)和 Props(属性)。那么就可以你已经掌握了 React 大部分知识了。
在 State,Props 之前,先来看一下 React 的基础。
JSX
const element = <h1>Hello, world!</h1>;
This funny tag syntax is neither a string nor HTML.
It is called JSX, and it is a syntax extension to JavaScript.
const element = <h1>Hello, world!</h1>;
这样的表达式就是 JSX 。它是 JavaScript 语法的延伸。
在 JSX 中,允许将 JS 代码和 HTML 标签一起使用。这样就可以使用熟悉 JS 来展开逻辑,使用熟悉的 HTML 来呈现 UI。不过这里有一点,就是一个 JSX 只能有一个根节点。所谓一个根节点,就是 HTML 最外面有且只有一个 HTML 标签。
const element = (
<div>
<h1>Hello<h1>
</div>
<h1>world!<h1>
)
像这样就是错误的,因为在最外面有和 div 同级的 h1。
const element = (
<div>
<h1>Hello<h1>
<h1>world!<h1>
</div>
)
改正的话,只需要将外面的 h1 移到 div里面,确保最外层只有一个 HTML 标签就好了。为什么要这样呢?因为这是 React 构建 **虚拟DOM(tree[树])**的需要。不知道虚拟DOM是什么鬼?不知道Tree[树]?没关系,我也不知道。后面会有 React 虚拟DOM的介绍。现在只需要记住这个规则就好了。
JSX 和 Typescript
如果使用 Typescript 来写 React,那 JSX 就相应的转变成了 TSX,其实本质还是不变的。
const element: JSX.Element = <h1>Hello, world!</h1>;
可以看到,element后面多了个类型,叫 JSX.Element
。我们看到的 React 应用 UI,都是通过 JSX.Element
映射到 HTML 上的。什么叫映射?额。。。这里可以当是呈现理解。
Component
**什么是 Component(组件)?**对于 React 来讲(对Vue、Angular也一样),Component(组件)就是构成 React 的零件。如果把一个 React 应用比作你手中的电脑的话。那么主机、显示屏、键盘就是这个应用的组件。当然,主机这一大的组件还可以分成其它的较小的组件–CPU、主板等。主机、显示屏、键盘等其它零件有效的拼凑在一起,就形成了你手中的电脑。React 应用也一样,也通过一个或多的组件的合理组合。所以,Component 也相当于 React 应用的零件。
在 Component 的生命周期中有一个重要的方法:render。生命周期?会在下一篇中介绍。
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
render
中返回的 HTML 就是该 Component 在UI上要呈现的样子。所以,编写 React Component的最终目的,就是通过逻辑,来控制 render 的返回结果。
JSX 是语法支持,Component 是理论支撑。那如何使 Component render 我们想要的 UI,那就需要涉及 Component 的两个重要概念:State、Props。
Props(属性)
属性就是一个事物的所属性质。对于不同事物,属性所代表的也有可能不一样。这里也只说 React Component 的 Props。
React 中,Component 的 Props 都是 Component 对其外部环境的变量的持有或引用。Component 所持有的 Props,并不能被其本身所改变,而相反的,若是 Component 所持有或引用的 Props 改变,那 Component 就要根据 Props 的变化,而做出相应的变化。
看一个例子(TodoApp)
class TodoApp extends React.Component {
...
render() {
return (
...
<TodoList items={this.state.items} />
...
)
}
...
}
class TodoList extends React.Component {
render() {
return (
<ul>
{this.props.items.map(item => (
<li key={item.id}>{item.text}</li>
))}
</ul>
);
}
}
在这个例子中,items
就是 TodoList
的 Props。items
的改变就会引起 TodoList 这个组件的改变。
这个例子有没有很熟悉的感觉。TodoList
是不是很像 HTML 中的自定义标签。与 HTML 标签是一样的,写法都是一样的。你会HTML,会JS,你就会 React!
在 Component中,可以通过 this.props(this.props.items
)直接拿到相应的 Props。是不是比 HTML 标签还要简单。
State(状态)
React 中,State(状态)就是对 Component 自身的描述。对于 Component 来讲,Props 是外界叫它怎么样它就怎么样,Component 是对 Props 没有控制力的。而 State 不一样,Component 对 State 是有绝对控制力的。不受外界干扰,就是老子想怎么样就怎么样。
这里我们也可以看到 React 的设计哲学:影响事物发展的无非就是外因和内因,而 Props 和 State就是 Component的外因和内因。
在 Component,是这样定义 State 的
class TodoApp extends React.Component {
constructor(props) {
...
this.state = {items: [], text: ''};
}
...
render() {
return (
<div>
<h3>TODO</h3>
<TodoList items={this.state.items} />
<form onSubmit={this.handleSubmit}>
<input onChange={this.handleChange} value={this.state.text} />
<button>{'Add #' + (this.state.items.length + 1)}</button>
</form>
</div>
);
}
...
}
在代码中,可以看到,state
是被 TodoApp Component
所完全持有的。Component 可以通过改变自身的 State (setState()
) 来改变 render 中逻辑。进而呈现不同UI。
State、Props 和 Typescript
使用 JS 写的 Component,Props 和 State表现的并不明显。虽然有 Flow 的解决方案。但 Typescript 的解决方案会更优雅和高效。
使用 Typescript 编写 React 组件,需要为组件定义好 Props 和 State。而这也被证明是个好的编码方式。可以帮助你构建更健壮的APP。至少是帮助了我。
...
interface OwnProps {
}
interface OwnState {
}
class TodoApp extends React.Component<OwnProps, OwnState> {
....
render(): JSX.Element {
return <div></div>
}
}
这样的代码结构可以使我们快速的知道 TodoApp 这个 Component,拥有什么样的Props,和什么样的State。代码变得更加清晰和紧凑。更利于对团队开发和维护。
感觉写了一锅粥