The Road to learn React书籍学习笔记(第二章)
The Road to learn React书籍学习笔记(第二章)
组件的内部状态
组件的内部状态也称为局部状态,允许保存、修改和删除在组件内部的属性,使用ES6类组件可以在构造函数中初始化组件的状态。构造函数只会在组件初始化的时候调用一次
类构造函数
class App extends Component{
constructor(props){
super(props);
}
}
使用ES6编写的组件有一个构造函数时,需要强制地使用 super()
方法, 因为这个 App组件
是 Component
的子类,因为需要在 App组件
声明 extends Component
也可以调用 super(props)
,它会在构造函数中设置 this.props
以供构造函数中访问。否则在构造函数中访问 this.props
,会得到 undefined
例子,组件的初始状态是一个列表
const list = [
{
title:'React',
url: 'https://facebook.github.io/react/',
author: 'Jordan Walke',
num_comments: 3,
points: 4,
objectID: 0,
}
];
class App extends Component{
constructor(props){
super(props);
this.state = {
list : list,
}
}
}
state
通过使用 this
绑定在类上,因此可以在整个组件中访问到 state
。通过 render()
方法可以映射一个在组件外定义静态列表
class App extends Component{
render(){
return(
<div className = "App">
{this.state.list.map(item =>
<div key = {item.objectID}>
<span><a href = {item.url}>{item.title}</a></span>
<span>{item.author}</span>
<span>{item.num_comments}</span>
<span>{item.points}</span>
</div>
)
}
</div>
);
}
}
现在list是㢟的一部分,它在组件的 state
中,可以从list添加、修改、删除列表项。组件的 render
会再次运行,可以简单修改组件内部状态,确保组件重新渲染并且展示从内部状态获取到的正确数据 修改 state
可以使用 setState()
方法来修改
ES6 对象初始化
初始化例子
const name = 'Laibh';
const user = {
name : name
};
当对象中属性名与变量名相同时可以如下操作
const name = 'Laibh';
const user = {
name
};
在应用程序中,列表变量名与状态属性名称共享同一名称
//ES5
this.state = {
list:list
}
//ES6
this.state = {
list
};
简写方法名
//ES5
var userService = {
getUserName :function(user){
return user.firstname + ' ' + user.lastname;
}
}
//ES6
const userService = {
getUserName(user){
return user.firstname + ' ' + user.lastname;
}
}
计算属性名
//ES5
var user = {
name:'Laibh'
}
//ES6
const key = 'name';
const user = {
[key] :'Laibh'
}
单向数据流
组件中有一些内部的 state
,练习 state
操作的好方式增加一些组件的互动 为列表增加一个删除按钮
class App extends Component {
render() {
return (
<div className="App">
{this.state.list.map(item =>
<div key={item.objectID}>
<span>
<a href={item.url}>{item.title}</a>
</span>
<span>{item.author}</span>
<span>{item.num_comments}</span>
<span>{item.points}</span>
<span>
<button
onClick={() => this.onDismiss(item.objectID)}
type="button"
>
Dismiss
</button>
</span>
</div>
)}
</div>
);
}
}
上面类中,onDismiss()
还没有被定义,它通过id来标识哪个应该被删除,此函数绑定到类,就成为了类方法,所以访问它的时候要用 this.onDismiss()
而不是用 onDismiss()
。this
对象是类的实例,为了将 onDismiss()
定义为类方法,需要在构造函数中绑定它。并定义它的逻辑功能
class App extends Component {
constructor(props) {
super(props);
this.state = {
list,
};
this.onDismiss = this.onDismiss.bind(this);
}
onDismiss(id) {
...
}
render() {
...
}
}
可以使用JavaScript内置的 filter
方法来删除列表的一项,它会遍历整个列表,通过条件来过滤,匹配的返回 true
并留在列表中
onDismiss(id){
const updateList = this.state.list.filter(function isNotId(item){
return item.objectID !== id
});
}
或者一行箭头函数
onDismiss(id){
const updateList = this.state.list.filter(item => item.objectID !== id);
}
接着要更新数据
this.setState({list:updateList});
绑定
类不会自动绑定 this
到实例上 需要自己绑定
constructor() {
super();
this.onClickMe = this.onClickMe.bind(this);
}
类的绑定方法也有人写在其他地方,例如render()函数中
render(){
return(
<button onClick = {this.onClickMe.bind(this)}>Click Me</button>
)
}
但是应该避免这样使用,因为它会在每次 render()
方法执行的时绑定类方法。组件每次更新都会导致性能消耗,当在构造函数中绑定的时候,绑定只会在组件实例化时运行一次,这样是一个更好的方式
另外有一些人剔除在构造函数中定义业务逻辑类方法
constructor(){
super();
this.onClick = () =>{
conlose.log(this);
}
}
这样随着时间推移会让构造函数变得混乱,避免使用。构造函数的目的只是实例化类以及所有的属性
事件处理
<button
onClick={() => this.onDismiss(item.objectID)}
type="button">
Dismiss
</button>
当传递一个参数到类的方法,需要将它封装到另一个(箭头)函数中,由于要传递给事件处理器使用,因为它必须是一个函数,而下面的这个代码不会工作。因为类方法会在浏览器中打开程序时候立即执行
<button onClick = {this.onDismiss(item.objectID)}>
Dismiss
</button>
倘若写成
<button onClick = {onDismiss}>
Dismiss
</button>
就不会立即执行,但是需要传参数,所以就不这么用
另外的一个解决方案是在外部定义一个包装函数,并且只将定义的函数传递给处理程序。因为需要访问特定的列表项,所以它必须位于 map
函数块的内部
class App extends Component{
render(){
return(
<div className = "App">
{this.state.list.map(item =>
const onHandldDismiss = () =>
this.onDismiss(item.objectID);
return(
<div key={item.objectID}>
<span>
<a href={item.url}>{item.title}</a>
</span>
<span>{item.author}</span>
<span>{item.num_comments}</span>
<span>{item.points}</span>
<span>
<button
onClick={onHandleDismiss}
type="button"
>
Dismiss
</button>
</span>
</div>
)
)}
</div>
)
}
}
在事件处理程序中使用箭头函数对性能会有影响
和表单互动
const list = [{
title: 'React',
url: 'https://facebook.github.io/react',
author: 'Jordan Walke',
num_comments: 3,
points: 4,
objectID: 0,
}, {
title: 'Redux',
url: 'https://github.com/reactjs/redux',
author: 'Dan Abramov, Andrew Clark',
num_comments: 2,
points: 5,
objectID: 1,
}];
const isSearched = searchText => item => item.title.toLowerCase().includes(searchText.toLowerCase());
class FormP extends Component{
constructor(props){
super(props);
this.state = {list,searchText:''};
this.onSearchChange = this.onSearchChange.bind(this);
this.onDismiss = this.onDismiss.bind(this);
}
onSearchChange(e){
this.setState({searchText:e.target.value});
}
onDismiss(id){
console.log(this);
const updateList = this.state.list.filter(item =>
item.objectID !== id
);
this.setState({list:updateList});
}
render(){
return(
<div className = "FormP">
<form>
<input type="text" onChange = {this.onSearchChange}/>
</form>
{this.state.list.filter(isSearched(this.state.searchText)).map(
item =>
<div key = {item.objectID}>
<span>
<a href= {item.url}>{item.title}</a>
</span>
<span>{item.author}</span>
<span>{item.num_comments}</span>
<span>{item.points}</span>
<span>
<button onClick = {()=>this.onDismiss(item.objectID)}>Dismiss</button>
</span>
</div>
)}
</div>
)
}
}
export default FormP;
ES6 解构
在JavaScript ES6 中有一个更方便的方法来访问对象和数组的属性,叫做解构。
const user = {
firsname : 'L',
lastname : 'binhong'
}
//ES5
var firstname = user.firstname;
var lastname = user.lastname;
console.log(firstname + '' +lastname);
//ES6
const {firstname, lastname} = user;
conlose.log(firstname + '' +lastname);
在JavaScript ES5中每次访问对象的属性都需要额外添加一行代码,但是ES6中就可以在一行中进行,可读性最好的方法就是将对象解构成多个属性时使用多行 对于数组也可以使用解构,可以保持代码的可读性
const user = ['1','2','3'];
const [
a,
b,
c
] = user;
console.log(a,b,c); //1,2,3
受控组件
表单元素 <input>
/<select>
/<textarea>
会以元素HTML的形式保存它们自己的状态,一旦有人从外部做了修改,就会修改内部的值,在React中这被称为不受控组件,因为它们自己处理状态,在React中,我们得把它们变成 受控元素
class App extends Componet{
render(){
const {searchText,list} = this.state;
return(
<div className = "App">
<form>
<input
type = "text"
value = {searchText}
onChange = {this.onSearchChange}
></input>
</form>
</div>
)
}
}
现在输入框的单项数据流循环是自包含的,组件内部状态是输入框的唯一数据来源
拆分组件
用于搜索的输入组件和一个用于展示的列表组件
class App extends Componet{
render(){
const {searchText,list} = this.state;
return(
<div className = "App">
<Search />
<Table />
</div>
)
}
}
在组件传递属性并在组件中使用,App组件需要传递本地状态 state
托管的属性和它自己的类方法
class App extends Component{
render(){
const {searchText,list} = this.state;
return(
<div>
<Search
value = {searchText}
onChange = {this.onSearchChange} />
<Table
list = {list}
pattern = {searchText}
onDismiss = {this.onDismiss} />
</div>
)
}
}
Search组件
class Search extends Component{
render(){
const {value,onChange} = this.props;
return(
<form>
<input
type = "text"
value = {value}
onChange = {onChange} />
</form>
)
}
}
Table组件
class Table extends Component{
render(){
const {list,pattern.onDismiss} = this.props;
return(
<div>
{list.filter(isSearched(pattern)).map(item =>
<div key = {item.objectID}>
<span><a href = {item.url}>{item.title}</a></span>
<span>{item.title}</span>
<soan>{item.points}</span>
<span>{item.num_comments}</span>
<button onClick ={() => onDismiss(item.objectID)}>
Dismiss
</button>
</div>
)}
</div>
)
}
}
可组合组件
在 props
对象中还有一个小小的属性可以供使用: children
属性.通过这个属性可以将元素从上层传递到组件中,这些元素对组件来说是未知的,但是却为组件互相结合提供了可能性、 下例中,将一个文本作为子元素传递到Search组件中
class App extends Component{
render(){
const {searchText,list} = user;
return(
<div>
<Search
value = {searchText}
onChange = {this.onSearchChange} />
)
}
}
在 Search
组件可以从 props
对象中解构出 children
属性,就可以指定它应该在哪里显示
class Search extends Component{
render(){
const {value,onChange,children} = this.props;
return(
<form>
{children}
<input
type = "text"
value = {value}
onChange = {onChange} />
}
</form>
)
}
}
可复用组件
可复用和可组合组件帮助理解合理的组件分层,它们是React视图层的基础
class Button extends Component{
render(){
const {onClick,className,children} = this.props;
return(
<button
onClick = {onClick}
className = {className}
type = "button">
{children}
</button>
)
}
}
Button组件拥有单一可信数据源,一个Button组件可以立即重构所有button。一个Button组件统治了所有button
<Button onclick = {() => onDismiss(item.objectID)}>Dissmiss</Button>
函数式无状态组件(function stateless componenet)
这类组件就是函数,它们接受一个输入并返回一个输出。输入时props,输出就是一个普通的JSX组件实例。函数式无状态组件是函数,并且它们没有本地状态。不能通过 this.state
或者是 this.setState()
来访问或者更新状态,因为这里没有 this
对象,此外,它也没有生命周期方法。 constructor()
与 render()
就是其中两个。 constructor
在一个组件的生命周期只执行一次,而 render()
方法只会在最开始执行一次
ES6 类组件
在类的定义中,它们继承自 React
组件。 extend
会注册所有的生命周期方法,只要在 React component API
中,都可以在组件中使用。通过这种方式,可以使用 render()
方法,此外还可以通过使用 this.state
和 this.setState()
来存储和操作 state
把上例的Search组件重构为一个函数式无状态组件
function Search(props){
const {value,onChange,children} = props;
return{
<form>
{children}<input
type = "text"
value = {value}
onChange = {onChange} />
</form>
}
}
或者将参数放在函数里面
function Search({value,onChange,children}){
return{
<form>
{children}<input
type = "text"
value = {value}
onChange = {onChange} />
</form>
}
}
然后ES6 箭头函数一波
const Search = ({value,onChange,children}) =>
<form>
{children}<input
type = "text"
value = {value}
onChange = {onChange} />
</form>
如果想在ES6箭头函数写法中做些事情的话 可以这样写
const Search = ({value,onChange,children}) => {
//do something
return(
<form>
{children}<input
type = "text"
value = {value}
onChange = {onChange} />
</form>
)
}
给组件声明样式
可以复用 src/App.css
或者 src/index.css
文件
The Road to learn React书籍学习笔记(第二章)的更多相关文章
- The Road to learn React书籍学习笔记(第一章)
react灵活的生态圈 Small Application Boilerplate: create-react-app Utility: JavaScript ES6 and beyond Styli ...
- The Road to learn React书籍学习笔记(第三章)
The Road to learn React书籍学习笔记(第三章) 代码详情 声明周期方法 通过之前的学习,可以了解到ES6 类组件中的生命周期方法 constructor() 和 render() ...
- The Road to learn React书籍学习笔记(第四章)
高级React组件 本章将重点介绍高级 React 组件的实现.我们将了解什么是高阶组件以及如何实现它们.此外,我们还将深入探讨 React 中更高级的主题,并用它实现复杂的交互功能. 引用 DOM ...
- 《DOM Scripting》学习笔记-——第二章 js语法
<Dom Scripting>学习笔记 第二章 Javascript语法 本章内容: 1.语句. 2.变量和数组. 3.运算符. 4.条件语句和循环语句. 5.函数和对象. 语句(stat ...
- [HeadFrist-HTMLCSS学习笔记]第二章深入了解超文本:认识HTML中的“HT”
[HeadFrist-HTMLCSS学习笔记]第二章深入了解超文本:认识HTML中的"HT" 敲黑板!!! 创建HTML超链接 <a>链接文本(此处会有下划线,可以单击 ...
- 交换机安全学习笔记 第二章 MAC地址泛洪攻击
本文为书中相关知识的摘要,由于书中以思科设备为配置依据,所以笔记中补充了华为.H3C设备的相关配置.华为设备配置参考华为S2352EI 产品版本:V100R005C01文档版本:02. H3C配置参 ...
- Java 学习笔记 ------第二章 从JDK到IDE
本章学习目标: 了解与设定PATH 了解与指定CLASSPATH 了解与指定SOURCEPATH 使用package与import管理类别 初步认识JDK与IDE的对应关系 一.第一个Java程序 工 ...
- J2EE学习笔记-第二章(Web应用初步)
首先要理解一些概念的词语,到底这些是什么(当我读懂了后,会逐一填补完整,现在我真的有点混淆) web组件-相当于功能性的组件,就像是零件,汽车的轮胎,汽车的门,所有组件组合后,才能成为一辆车,有时候也 ...
- 《Python基础教程(第二版)》学习笔记 -> 第二章 列表和元组
本章将引入一个新的概念:数据结构. 数据结构是通过某种方式阻止在一起的数据元素的集合,这些数据元素可以是数字或者字符,设置可以是其他数据结构. Python中,最基本的数据结构是序列(Sequence ...
随机推荐
- 并发集合 System.Collections.Concurrent 命名空间
System.Collections.Concurrent 命名空间提供多个线程安全集合类. 当有多个线程并发访问集合时,应使用这些类代替 System.Collections 和 System.Co ...
- C++课堂作业(2)
github的链接: https://github.com/deepYY/object-oriented/tree/master/PAT.1025 题目 给定一个常数K以及一个单链表L,请编写程序将L ...
- 异常处理与MiniDump详解(2) 智能指针与C++异常
write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie 讨论新闻组及文件 一. 综述 <异常处理与MiniDump详解(1) C++异常>稍 ...
- [T-ARA][20090729]
歌词来源:http://music.163.com/#/song?id=484058959 在基本发音规则之上,考虑到了音变的某些情况,最后结合听力搞定的一版歌词发音(只要学完养乐多老师的教程应该读起 ...
- angularjs中factory, service和provider
在Angular里面,services作为单例对象在需要到的时候被创建,只有在应用生命周期结束的时候(关闭浏览器)才会被清除.而controllers在不需要的时候就会被销毁了(因为service的底 ...
- C语言支持的四种变量存储类型
http://blog.csdn.net/zhandoushi1982/article/details/5425835 一)auto:auto称为自动变量(局部变量).局部变量是指在函数内部说明的变量 ...
- BZOJ2780:[SPOJ8093]Sevenk Love Oimaster(广义SAM)
Description Oimaster and sevenk love each other. But recently,sevenk heard that a girl named ChuYuXu ...
- 如何寫一個自定義控件/vs2010生成Dll文件并引用dll(C#)
1.最簡單的例子 首先你先新建->項目->類庫.然後右鍵項目.添加一個用戶控件.設置其用戶控件繼承button. egg: namespace ClassLibrary1{ publ ...
- jquery mobile各类组件刷新方法
1.Combobox or select dropdowns var myselect = $("#sCountry"); myselect[0].selectedIndex ...
- RAID基本知识
RAID是英文Redundant Array of Independent Disks(独立磁盘冗余阵列),简称磁盘阵列.下面将各个级别的RAID介绍如下. 一.为什么使用Raid? 1.对磁盘高速存 ...