react学习笔记(二)
react单项数据流
父组件向子组件传递的参数,是不可以在子组件直接修改的,会报错,父组件传给子组件的都是只读属性。
函数式编程
react是函数式编程的框架,优点是1:代码清晰,知道各个部分是干嘛的,优点2:代码更容易测试。
调试工具的安装和使用
_propTypes校验传递的值
import PropTypes from ‘prop-types’
进行校验要在子组件的类的外面
在子组件的类的外面写
MyService.propTypes = {item: PropTypes.string,index: PropTypes.number,remove: PropTypes.func
}
func: 一定要传方法
PropTypes.string.isRequired : 表示一定要传这个,不能不传
默认值
XiaojiejiItem.defaultProps = {avname: '松岛枫'
}
react中,如何决定要不要将部分代码封装成组件
如果 UI 中有一部分被多次使用,或者组件本身就足够复杂,那么它就是一个可提取出独立组件的候选项。
直接复制一下react官网上关于函数组件解析流程的描述
class Clock extends React.Component {constructor(props) {super(props);this.state = {date: new Date()};}componentDidMount() {this.timerID = setInterval(() => this.tick(),1000);}componentWillUnmount() {clearInterval(this.timerID);}tick() {this.setState({date: new Date()});}render() {return (<div><h1>Hello, world!</h1><h2>It is {this.state.date.toLocaleTimeString()}.</h2></div>);}
}ReactDOM.render(<Clock />,document.getElementById('root')
);
- 当
<Clock />
被传给ReactDOM.render()
的时候,React 会调用Clock
组件的构造函数。因为Clock
需要显示当前的时间,所以它会用一个包含当前时间的对象来初始化this.state
。我们会在之后更新 state。 - 之后 React 会调用组件的
render()
方法。这就是 React 确定该在页面上展示什么的方式。然后 React 更新 DOM 来匹配Clock
渲染的输出。 - 当
Clock
的输出被插入到 DOM 中后,React 就会调用ComponentDidMount()
生命周期方法。在这个方法中,Clock
组件向浏览器请求设置一个计时器来每秒调用一次组件的tick()
方法。 - 浏览器每秒都会调用一次
tick()
方法。 在这方法之中,Clock
组件会通过调用setState()
来计划进行一次 UI 更新。得益于setState()
的调用,React 能够知道 state 已经改变了,然后会重新调用render()
方法来确定页面上该显示什么。这一次,render()
方法中的this.state.date
就不一样了,如此以来就会渲染输出更新过的时间。React 也会相应的更新 DOM。 - 一旦
Clock
组件从 DOM 中被移除,React 就会调用componentWillUnmount()
生命周期方法,这样计时器就停止了。
把组件传递给ReactDOM.render() =>
React调用Clock的构造函数并初始化数据(state) =>
React调用组件的render()方法,更新DOM来匹配Clock渲染的输出 =>
Clock输出被插入到DOM中,调用生命周期,并且执行一个每秒执行一次的tick方法 => tick方法中,clock组件会调用setState来更新UI,得益于setState的调用,react知道state已经改变了,然后重新调用render()来确定页面显示什么
正确地使用state
- 不直接修改
- 更新可能是异步的,出于性能考虑,React 可能会把多个 setState() 调用合并成一个调用。
因为 this.props 和 this.state 可能会异步更新,所以你不要依赖他们的值来更新下一个状态。
// Wrong
this.setState({counter: this.state.counter + this.props.increment,
});// Correct
this.setState((state, props) => ({counter: state.counter + props.increment
}));
单向数据流
组件无法知道其他组件是有状态还是无状态的,state是组件自己私有的,其他组件无法访问,组件可以选择把state作为props向下传递给它的子组件中。组件接收参数时,不知道这个数据是从哪里来的。
发现问题:有状态无状态是啥?
有状态无状态是啥
有状态组件:用class
关键字创建的组件,有自己的私有数据state和生命周期函数
无状态组件:用构造function
函数创建出来的组件,只有props,没有sate和生命周期函数
无状态组件,由于没有自己的state和生命周期函数,所以运行效率高
什么时候用无状态组价?
组件本身不需要负责UI变化,不包括子组件
事件绑定中this处理的三种办法
1.在组件的constructor
中绑定
2.在有状态(class声明的)组件中,用箭头函数
3.在jsx中写,但不推荐这种写法,因为如果该回调函数作为prop传入子组件,这些组件可能进行额外的重新渲染,印象性能。
条件渲染
比较简单就不写太多了
与运算符&&
可以在JSX中嵌入表达式,可以方便地进行元素的条件渲染
在react的if中写循环怎么写?
工作中的场景,当列表的数据大于0时,才渲染列表
<ul>{ this.state.list.length > 0 && this.state.list.map((item, index) => {return <li key={item+index} ><MyService deleteItem={this.remove.bind(this)} index={index} key={item+index} item={item}></MyService></li>})}
</ul>
简单的切换选项卡效果
constructor(props){super(props)this.state={activeVal: 0}}
...省略代码
render(){return (<Fragment><button onClick={this.changeTab.bind(this,0)}>科技新闻</button><button onClick={this.changeTab.bind(this,1)}>娱乐新闻</button><div>{this.activeVal === 0 ? <h1>科技新闻</h1> : <h1>娱乐新闻</h1>}</div></Fragment>)
}
...省略代码...
changeTab(idx){this.setState({activeVal: idx})
}
阻止组件渲染
让render
方法返回null
,就不会进行渲染了。
render方法返回null不会影响组件的生命周期。
列表渲染与key
列表渲染需要有key,因为键是React用来识别DOM元素的唯一方法,如果将一个项目推到列表中或是删除中间的某一项,如果键与前面的相同,React会以为这个新插入的元素和前面的元素是同一个。
案例地址
当没有输入key时,react会默认把index当做key。但这是suboptimal(未达标准的)。
Much better推荐用法:
安装并且使用shortid
var shortid = require('shortid')function createNewTodo (text) {return {id: shortid.generate(),text}
}
参考文章:Index as a key is an anti-pattern
PropTypes
可以设置默认传递参数的类型
import PropTypes from 'prop-types'MyService.propTypes = {item: PropTypes.string,index: PropTypes.number,remove: PropTypes.func
}
ref与ref的坑
- ref的用法:
// jsx
<input ref={(input)=>this.input = input} onchange={this.inputChange.bind(this)}></input>
...省略代码inputChange(e){this.setData({data: e.target.value})console.log(this.input.clientHeight) // 用了ref绑定,这里可以获得这个绑定dom元素的相关信息
}
ref的坑
<ul ref={(ul)=>{this.ul=ul}}>{this.state.list.map((item,index)=>{return (<XiaojiejieItem key={index+item} content={item}index={index}deleteItem={this.deleteItem.bind(this)}/>)})}
</ul>
绑定后可以在addList()方法中,获取当前
addList(){this.setState({list:[...this.state.list,this.state.inputValue],inputValue:''})//关键代码--------------startconsole.log(this.ul.querySelectorAll('div').length)//关键代码--------------end}
这时候打开控制台,会发现length少一个,这是因为setState是一个异步函数,还没等虚拟dom渲染,console.log就已经执行了。
为了解决这个问题,可以使用setState的回调函数
addList(){this.setState({list:[...this.state.list,this.state.inputValue],inputValue:''},()=>{console.log(this.ul.querySelectorAll('div').length)})
}
React生命周期
Initialization
:初始化阶段
mounting
:挂载阶段
updation
:更新阶段
Unmounting
:销毁阶段
- constructor 不算生命周期函数,constructor算构造函数,属于
initialization
阶段,定义prop和state
mounting阶段
1.componentWillMount(新版本可能废弃不推荐使用)
:在组件即将被挂载到页面的时刻执行
2.render
:state或props发生变化时执行
3.componentDidMount
:组件挂载完成时执行
Updation阶段
1.shouldComponentUpdate
:组件更新前执行
要求返回一个布尔类型的结果,必须有返回值,这里就直接返回一个true了
shouldComponentUpdate(){console.log('shouldComponentUpdate---组件发生改变前执行')return true
}
如果return 是false的话,这个组件的render就不会执行了
2.componentWillUpdate
:这个函数在组件更新之前,shouldComponentUpdate
执行之后执行,如果shouldComponentUpdate
函数返回值为false,该函数就不会执行了
3.componentDidUpdate
:进行更新
执行顺序:
- shouldComponentUpdate
- componentWillUpdate
- render
- componentWillUpdate
componentWillReceiveProps
:
子组件接收父组件传来的参数,父组render函数重新执行时,这个函数就执行
- 也就是说这个组件第一次存在于Dom中,函数是不会被执行的;
- 如果已经存在于Dom中,函数才会被执行。
新的生命周期
https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html
getDerivedStateFromProps
getDerivedStateFromProps
在组件实例化后render前被调用。它可以返回一个对象来更新状态,或者返回 null 来表示新的道具不需要任何状态更新。
class Example extends React.Component {static getDerivedStateFromProps(props, state) {// ...}
}
To-do 的性能优化
打开React Developer Tools
中的setting,设置highlight Updates
。
这时候可以看到
当input在修改时,其他无关的组件如<service>
组件也被重新渲染,这样会影响性能,因此我们可以利用生命周期函数来进行优化。
知乎问题
为什么vue没有shouldComponentUpdate?
npm install的三种差别
npm install
:安装到项目下但不产生依赖
npm install --save
:安装到项目下并且产生依赖,可以在package.json中的dependencies
中查看
npm install --save-dev
:只在开发环境中需要的安装到这里
save是默认的,你什么都不写就相当于写了–save,因此npm install 时默认的时npm install --save
缩写:
npm i -S
: npm install --save
npm i -D
: npm install --save-dev
参考:
技术胖React教程
Redux
react ui组件和容器组件
ui组件(只负责页面渲染)
容器组件负责逻辑
普通组件
无状态组件(只有render函数的话,就可以用无状态组件了,可以省去生命周期函数,优化代码)
ui组件和无状态组件的区别
// ui组件
import React, { Component } from 'react';
import { Input, Button, List } from 'antd'class TodoListUI extends Component {state = { }render() { return ( <div style={{marginTop:'10px',marginLeft:'10px'}}><Input value={this.props.inputValue}placeholder="todo info"onChange={this.props.handleInputChange}style={{width:'300px',marginRight:'10px'}}/><Button onClick={this.props.handleBtnClick} type="primary" >提交</Button><Liststyle={{width:'300px',marginTop:'10px'}}bordereddataSource={this.props.list}renderItem={(item, index) => (<List.Item onClick={() => {this.props.handleItemDelete(index)}} >{item}</List.Item>)}/></div>);}
}export default TodoListUI;
// 无状态组件,就是一个函数,当组件只有render函数的时候很适合使用
// 改写上面的ui组件
import React from 'react';
import { Input, Button, List } from 'antd'function TodoListUI = (props) =>{return (<div style={{marginTop:'10px',marginLeft:'10px'}}><Input value={this.props.inputValue}placeholder="todo info"onChange={this.props.handleInputChange}style={{width:'300px',marginRight:'10px'}}/><Button onClick={this.props.handleBtnClick} type="primary" >提交</Button><Liststyle={{width:'300px',marginTop:'10px'}}bordereddataSource={this.props.list}renderItem={(item, index) => (<List.Item onClick={() => {this.props.handleItemDelete(index)}} >{item}</List.Item>)}/></div>)
}export default TodoListUI;
封装全局的加载组件
https://www.cnblogs.com/leiting/p/10531548.html
react学习笔记(二)相关推荐
- React学习笔记二:实现一个数字时钟
<!DOCTYPE html> <html lang="zhm"><head><meta charset="UTF-8" ...
- React学习笔记二——react-router
2019独角兽企业重金招聘Python工程师标准>>> 今天写了一个关于react-router的demo,因为不喜欢下载太多的依赖包,所以就直接引得js,解析会比较慢一些. 首先先 ...
- React学习笔记二 通过柯里化函数实现带参数的事件绑定
class Login extends React.Component {state = {username: '',password: ''}saveFormData = (type) => ...
- React学习笔记(二) | 受控组件
React组件 目标 能够知道受控组件是什么 能够写出受控组件 了解非受控组件 表单处理 受控组件(★★★) HTML中的表单元素是可输入的,也就是有自己的可变状态 而React中可变状态通常保存在s ...
- React学习笔记 - 组件Props
React Learn Note 4 React学习笔记(四) 标签(空格分隔): React JavaScript 三.组件&Props 组件可以将UI切分成一些独立的.可复用的部件,这样你 ...
- ES6学习笔记二arrow functions 箭头函数、template string、destructuring
接着上一篇的说. arrow functions 箭头函数 => 更便捷的函数声明 document.getElementById("click_1").onclick = ...
- qml学习笔记(二):可视化元素基类Item详解(上半场anchors等等)
原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7851 ...
- [转载]dorado学习笔记(二)
原文地址:dorado学习笔记(二)作者:傻掛 ·isFirst, isLast在什么情况下使用?在遍历dataset的时候会用到 ·dorado执行的顺序,首先由jsp发送请求,调用相关的ViewM ...
- react学习笔记1--基础知识
什么是react A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES[React是一个用于构建用户界面的JavaScript库.] React之所以快, ...
- PyTorch学习笔记(二)——回归
PyTorch学习笔记(二)--回归 本文主要是用PyTorch来实现一个简单的回归任务. 编辑器:spyder 1.引入相应的包及生成伪数据 import torch import torch.nn ...
最新文章
- UML用例图概要(转)
- 【机器学习课程01】李宏毅2020年机器学习课程开课啦!!!
- 01_初识Matplotlib、Figure的组成、绘图函数的输入类型、第一个例子(学习笔记)
- Qt创建工程及导入资源图片
- vue computed使用_vue computed正确使用方式
- 【使用注意】Jsoup的select方法
- 19-数据持久化-Bind Mounting
- git常用命令之log
- 消息队列的使用场景(转载c)
- 分享个markdownpad2的授权key
- Linux7运维视频教程
- 1.7 新概念 量词
- ecs 导出mysql文件_mysql导出数据库文件
- 固态硬盘的计算机需要进行磁盘碎片整理吗,固态硬盘为什么不需要电脑磁盘碎片整理?...
- reporting php,php error_reporting函数怎么用
- javac.exe 、 java.exe、 javaw.exe 、 javaws.exe有什么区别?
- 小程中的web-view缓存问题
- 东风风神酷我音乐显示服务器错误,评测:东风风神奕炫GS中控屏幕多媒体系统使用说明...
- 叶子结点和分支节点_什么是叶子节点,度?根节点?
- TreeSize Free
热门文章
- 西门子哪款plc支持c语言,西门子PLC的几种编程语言简单介绍
- 安卓如何调出软键盘_系统软键盘Android在外接物理键盘时,如何强制调用系统软键盘?...
- 奇迹暖暖登录显示服务器满,奇迹暖暖登录不是全屏
- MySQL基础学习(尚硅谷 婷姐)自学笔记_001
- 快手科技2020年总收入人民币588亿元,同比增长50.2%
- Nginx 配置长连接
- python多进程假死
- python将pvr格式转换成pvr.ccz的代码
- ioi2020集训队作业_IOI2020 集训队作业 Part 3
- silverlight ajax调用,基于RIA的AJAX和Silverlight研究与应用