

React.js 复习笔记:组件组合与复用
source link: https://blog.jimmylv.info/2015-05-14-learning-reactjs/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Why React?
React 的创建是为了数据的频繁交互:通过组件化轻松展现数据;数据改变时,自动更新 UI,并且只更新有改变的部分。
var component = React.createClass()
用来创建一个组件类,组件类似于函数,可以把它看作有着 props 和 state 状态并且可以返回(render()
)HTML 结构的函数。
React.render()
将 React 的模板转化为 HTML,并插入到相应的 DOM 结构中,React.render
方法可以渲染 HTML 结构,也可以渲染 React 组件。
渲染 HTML 标签
声明变量采用首字母小写
var myDivElement = <div className="foo" />
React.render(myDivElement, document.body)
渲染 React 组件
声明变量采用首字母大写
var MyComponent = React.createClass({
/*...*/
})
var myElement = <MyComponent someProperty={true} />
React.render(myElement, document.body)
关于 JSX
组件应该关注分离,而不是模板和展现逻辑分离。结构化标记和生成结构化标记的代码是紧密关联的,此外,展现逻辑一般都很复杂,使用模板语言会使展现变得笨重。
标签的属性 class 和 for,需要写成 className 和 htmlFor,因为两个属性是 JavaScript 的保留字和关键字,无论你是否使用 JSX。
JSX 是 HTML 和 JavaScript 混写的语法,当遇到<
,JSX 就当 HTML 解析,遇到{
就当 JavaScript 解析。
虚拟 DOM
React 使用了内部的虚拟 DOM,当数据发生改变,先在虚拟 DOM 中计算变化,最后将变动的部分反应到真实的 DOM 中。
#app.js
var HelloWorld = React.createClass({
render: function () {
return (
<p>
Hello,<input type="text" placeholder="Your name here" value={this.props.date.toTimeString()}/>!
It is {this.props.date.toTimeString()}
</p>
);
}
});
setInterval(function () {
React.render(
<HelloWorld date={new Date()} />,
document.getElementById('example')
);
}, 500);
input 相对于这个组件来说,是它的属性,并且没有嵌入动态的数据。而在 React 的设定中,属性是不可变的。
例如 component 组件有两个动态的属性 foo 和 bar:
var component = <Component foo={x} bar={y} />;
而实际上,有些属性可能是后续添加的,当需要拓展我们的属性的时候,定义个一个属性对象,并通过{...props}
的方式引入,React 会帮我们拷贝到组件的 props 属性中。
可以使用属性延伸覆盖原来的属性值:
var Component = React.createClass({
render: function () {
return (
<div {...this.props} title="zzz">
this is a div
</div>
)
},
})
React.render(<Component name="xxx" title="yyy" />, document.body)
style 属性
在 React 中写行内样式时,要这样写,不能采用引号的书写方式
React.render(<div style=>xxxxx</div>, document.body)
this.props
var HelloWorld = React.createClass({
render: function () {
return <div data-title={this.props.title}>{this.props.content}</div>
},
})
React.render(<HelloWorld title="this is title" content="this is content" />, document.body)
通过this.props
我们可以拿到组件被使用时的属性,this.props 就是组件的属性集合。React 将组件的子节点封装到了 children 属性中,当子节点只有一个的时候直接通过this.props.children
获取子节点的内容。当子节点的个数大于 1 时,this.props.children
返回的是一个数组。
this.state
this.state
是同 UI 交互最重要的属性,this 指向组件的实例。React 将 UI 简单的看作状态机,拥有各种各样的状态,并在各种状态间切换,这样很容易保持 UI 的一致性。在 React 中,你只要改变组件的状态,就会重新渲染 UI,React 会在最有效的方式下更新 DOM。通过调用setState(data, callback)
方法,改变状态,就会触发 React 更新 UI。
var ColorButton = React.createClass({
getInitialState: function () {
return { bColor: 'green' }
},
render: function () {
return (
<button onClick={this.handleClick} style=>
click
</button>
)
},
// 点击按钮,切换按钮的颜色:
handleClick: function (event) {
this.setState({ bColor: this.state.bColor === 'green' ? 'red' : 'green' })
},
})
React.render(<ColorButton />, document.body)
getInitialState
是用来初始化 state,handleClick
是用来处理我们点击事件的,如果想要拿到当前操作的 DOM,通过参数 event 获取。
两种属性的运用
大部分的组件应该从 props 属性中获取数据并渲染。但有的时候组件得相应用户输入,同服务器交互,这些情况下会用到 state。React 的官方说法是:尽可能的保持你的组件无状态化。为了实现这个目标,得保持你的状态同业务逻辑分离,并减少冗余信息,尽可能保持组件的单一职责。
React 官方推荐的一种模式就是:构建几个无状态的组件用来渲染数据,在这些之上构建一个有状态的组件同用户和服务交互,数据通过 props 传递给无状态的组件。
var RenderComponent = React.createClass({
render: function () {
return (
<ul>
{this.props['data-list'].map(function (item) {
return <li>{item}</li>
})}
</ul>
)
},
})
var StateComponent = React.createClass({
getInitialState: function () {
return { list: ['xxx', 'yyy'] }
},
render: function () {
return (
<div>
<button onClick={this.handleClick}>click</button>
<RenderComponent data-list={this.state.list} />
</div>
)
},
handleClick: function () {
this.setState({ list: [1, 2, 3] })
},
})
React.render(<StateComponent />, document.body)
React 还允许我们下面的方式自定义属性的默认值:
var ComponentWithDefaultProps = React.createClass({
getDefaultProps: function () {
return {
value: 'default value',
}
},
/* ... */
})
getDefaultProps()
的值将会被缓存,当this.props.value
的值没有被父组件指定时,将会使用这个默认值。
官方示例:
var Avatar = React.createClass({
render: function () {
return (
<div>
<ProfilePic username={this.props.username} />
<ProfileLink username={this.props.username} />
</div>
)
},
})
var ProfilePic = React.createClass({
render: function () {
return <img src={'http://graph.facebook.com/' + this.props.username + '/picture'} />
},
})
var ProfileLink = React.createClass({
render: function () {
return <a href={'http://www.facebook.com/' + this.props.username}>{this.props.username}</a>
},
})
React.render(<Avatar username="pwh" />, document.getElementById('example'))
上面的例子中,组件 Avatar 包含了组件 ProfilePic 和 ProfileLink。在 React 当中,所有者就是可以设置其他组件 props 的组件。说的通俗点:如果组件 X 出现在了组件 Y 的 render()方法中,那么组件 Y 就是所有者。正如我们之前所讨论的,组件不能改变 props—props 应同所有者初始化它们时保持一致。
父子节点的关系
一定要弄清所有者和被所有关系,父子关系的区别。所有者和被所有者关系是针对 React 组件的,父子关系是针对 DOM 结构的。来上面的例子来说,Avatar 是所有者,拥有 div、ProfilePic、ProfileLink,而 div 和 ProfilePic、ProfileLink 则是父子关系。
<Parent><Child /></Parent>
创建实例,Parent 可以通过 this.props.children 获取到它的子内容。
动态子节点
在 React 更新 DOM 的过程中,子节点是根据它们渲染的顺序调节的。实际上,React 改变第一个子节点的内容,然后删除最后一个节点。所以当数据来自于搜索结果或者新的组件被添加到数据流里,在这种情况下,每个子节点都需要保持唯一的标识,此时可以给每个子节点添加 key 属性。
var Component = React.createClass({
render: function () {
var results = this.props.results
return (
<ol>
{results.map(function (result) {
return <li key={result.id}>{result.text}</li>
})}
</ol>
)
},
})
单向数据流
在 React 当中,数据通过 props 从所有者向子节点传递,这就是所谓的单向数据绑定了。所有者将它拥有的组件 props 绑定到它的 props 或者 state,这个过程将会递归进行。数据改变就会通过组件到子组件再到子节点即所有的 DOM 节点,最终反映到 UI 层。
Recommend
-
57
组件复用那些事儿 - React 实现按需加载轮子
-
70
-
39
VUE的灵魂在于组件化开发,在VUE的世界里,我们可以把一切东西定义为组件,包括每一个路由对应的页面。而我之前开发都没有充分认识到页面也是组件这个概念,无形中增加了很多工作量,直到这两天写网站后台某个需求时才突然醒悟,原来路由...
-
12
React 源码版本: v16.9.0 源码注释笔记:airingursb/react 如何复用和扩展 React 组件的状态逻辑?具体而言,有以下五种方案: Mixins Class...
-
10
易懂好上手的transition-group函数式复用组件Vue.js中内置了强大好用的过渡和动画辅助系统,让我们在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。Vue提供的 <transition> 和 <transition-group>
-
9
基础组件设计 前言 首先,我们先介绍一下 Swoole\Coroutine\Client 的一个限制,那便是同一个连接,不允许同时被两个协程绑定,我们可以进行以下测试。 <?php run(function () {...
-
5
Blazor 是 .NET 最新的前端框架,可以基于 WebAssembly 或 SignalR (WebSocket)构建前端应用程序,基于 WebAssembly 托管模型的 Blazor 甚至可以离线运行。再加上可以共用 .NET 类...
-
5
Svelte入门——Web Components实现跨框架组件复用 Svelte 是构建 Web 应用程序的一种新方法,推出后一直不温不火,没有继Angular、React和VUE成为第四大框架,但也没有失去热度,无人问津。造成这种情况很重要的一个原因是,Svelte 的核...
-
5
在上节中,我们一起了解了如何使用Svelte封装Web Component,从而实现在不同页面间使用电子表格组件。 Svelte封装组件跨框架复用,带来的好处也十分明显: 1、使用框架开发,更容易维护 2、发布后没有框架依赖,其他任何场景都可以使用
-
4
多路由复用页面组件问题 - 甜点cc - 博客园 本文围绕 Vue Router 中路由组件复用问题展开 项目...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK