一、React编程优势以及特点
优势
1.声明式开发 节约大量DOM操作
2.可以与其他框架并存,如JQuery
3.组件化(包含无状态组件)
4.单向数据流 React父组件向子组件传值,子组件可以使用父组件传过来的值,但是不能直接修改父组件的内容
5.视图层框架 只着重于数据和页面渲染,大型项目 需要借助如 redux等来进行组件之间的传值、通信
6.函数式编程 维护程度简单、各司其职;便于代码自动化测试
不足
1、react中只是MVC模式的view部分,要依赖引入很多其他模块开发
2、当父组件进行重新渲染操作时,即使子组件的props或state没有做出任何改变,也会同样进行重新渲染。
特点
1、声明式设计:React采用声明方式,可以轻松描述应用
2、高效:React通过对DOM的模拟,最大限度的减少了与DOM的交互
3、灵活:React可以与已知的库或框架很好地配合
二、React零碎知识点(随时补充)
1、构造函数的固定写法
constructor(props){
super(props);
this.state = {
//定义一些 页面初始化的状态型如
inputValue:"",
list:[]
}
}
//在页面初始化的时候,construcotr构造函数会优于其他函数最早被执行
2、htmlFor、dangerousSetInnerHTML的意义与使用
<div>
//htmlFor可以使用户再点击输入内容的时候光标自动显示在input中,如下图
<label htmlFor="insertArea">请输入内容</label>
<input id="insertArea" />
</div>
htmlFor.gif
<ul>
// dangerouslySetInnerHTML 不转义标签 保留标签属性及样式
{
this.state.list.map((item, index) =>{
return <li dangerouslySetInnerHTML = {{__html:item}}></li>
})
}
</ul>
dangerouslySetInnerHTML.gif
3、父子组件的传值方式(不仅限于传值,还可以传递方法)
// content、index 为内容和索引;handleItemDel为方法
this.state.list.map((item,index) => {
return (
<TodoItem content={item} index={index} handleItemDel= {this.handleItemDelClick} />
)
})
4、对于直接写在展示内容中的逻辑处理
可以使用一个函数,把逻辑处理放到函数中,便于代码优化
class TodoList extends Component{
......
render(){
return (
<div>
{this.getTodoItem()}
</div>
)
}
getTodoItem(){
//TodoItem为一个子组件
return this.state.list.map((item,index) =>{
<TodoItem content={item} index={index} />
})
}
}
5、对于初始化状态值的操作。
react 对于初始化定义得状态值的操作使用this.setState
handeleBtnClick(){
//prevState表示修改前的数据 等价于this.state.list
//...es6的展开运算,...prevState.list 相等于拷贝this.state.list
this.setState((prevState) =>({
list:[...prevState.list,.....]
}))
}
6、propType与defaultProps
propType
限制要求父组件向子组件传值类型
// 父组件部分代码
import PropTypes from 'prop-types' //属性接收的强校验 脚手架工具自带
<TodoItem content={item} index={index} handleItemDelete={this.handleItemDelete} />
//子组件部分代码
TodoItem.propTypes = {
test:PropTypes.string.isRequired, // 要求 test 是字符串 必传
content: PropTypes.string, // 要求content 必须是字符串
handleItemDelete:PropTypes.func, // handleItemDelete 必须是函数
index:PropTypes.number
}
defaultProps
默认属性值。在页面初始化时,可以给某一个或某一些元素定义一个默认值。如上述代码test
父组件未给子组件传递,而且规定其为必传项,这时控制台会出现警告或报错,因此就需要用到defaultProps
TodoItem.defaultProps = {
test:'Hello'
}
7、虚拟DOM
普通实现:
1、state 数据(constructor 下初始化的数据)
2、JSX模板 (jsx代码)
3、数据+模板 结合,生成真实DOM,来显示
4、state 发生改变
5、数据+模板 结合,生成真实DOM,替换原始DOM
缺陷:
第一次生成了一个完成的DOM片段
第二次生成了一个完整的DOM片段
第二次的DOM替换第一次的DOM,非常耗性能
改良:
1、state 数据(constructor 下初始化的数据)
2、JSX模板 (jsx代码)
3、数据+模板 结合,生成真实DOM,来显示
4、state 发生改变
5、数据+模板 结合,生成真实DOM,并不直接替换原始DOM
6、新的DOM和原始DOM作比对 找差异
7、找出DOM发生的变化
8、只用新的DOM发生变化的部分 替换掉老的DOM中的部分
缺陷:性能提升并不明显
React 虚拟DOM
1、state 数据(constructor 下初始化的数据)
2、JSX模板 (jsx代码)
3、数据+ 模板 生成虚拟DOM(虚拟DOM就是一个JS对象,用它来描述真实DOM)
['div',{id:'abc'},['span',{},'hello world']]
(表述上面DOM对象)
4、用虚拟DOM的结构生成真实DOM,来显示
<div id="abc"><span>hello world</span></div>
5、state 发生改变
6、数据+ 模板 生成新的虚拟DOM(极大的提升了性能)(react 虚拟DOM 为同层比对)
['div',{id:'abc'},['span',{},'bye bye']]
7、比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中的内容(极大的提升了性能)
8、直接操作DOM、改变span中的内容
优点:
1、性能得到提升
2、使得跨端应用得以实现。React Native
ref
帮助我们在react中直接获取DOM元素使用的 一般情况,尽量不要使用,除非非用不可
class TodoList extends Component {
constructor(props){
super(props);
this.state = {
inputValue:'',
list:[]
}
this.handleInputChange = this.handleInputChange.bind(this)
this.handleBtnClick = this.handleBtnClick.bind(this)
}
render(){
return(
<input
id="insertArea"
className='input'
value={this.state.inputValue}
onChange={this.handleInputChange}
ref ={(input) =>{this.input = input}}
/>
<button onClick={this.handleBtnClick}>提交</button>
)
}
handleInputChange(e){
const value = this.input.value
}
handleBtnClick(){
// prevState 指的是修改数据之前的那一次数据 等价于this.state 避免直接修改了state的状态
this.setState((prevState) => ({
list:[...prevState.list, prevState.inputValue],
inputValue:''
}),()=>{
// setState 提供的第二个参数 当setState执行成功后执行 ref 获取DOM 操作改变内容在此执行
});
}
}
生命周期函数
是指函数在某一个时刻组件会自动调用执行的函数
挂载部分
componentWillMount
当组件即将被挂载到页面的时刻自动执行
render
页面渲染
componentDidMount
当组件被挂载到页面之后自动执行
数据更新部分
shouldComponentUpdate
组件被更新之前,会自动执行,返回一个布尔值。true/false
componentWillUpdate
组件被更新之前,会自动执行,但它在shouldComponentUpdate
之后被执行,如果shouldComponentUpdate
返回true,执行,返回false不执行
componentDidUpdate
组件更新完成之后执行
componentWillReceiveProps
当父组件传值props发生改变是触发
执行条件如下:
一个组件需要从父组件接收参数
如果该组件第一次存在于父组件中,不会执行
如果该组件之前已经存在于父组件中,才会自行
componentWillUnmount
当组件即将从页面中移除的时候去执行
diff算法
image.png1、把树形结构按照层级分解,只比较同级元素
2、通过给列表结构的每个单个元素添加唯一key值进行区分同层次的子节点的比较
3、React只会匹配相同 class 的component(这里的class指的是组件的名字)
4、合并操作,调用component的setState方法的时候,React将其标记为dirty 到每一个事件循环结束,React检查所有标记dirty的component重新绘制
5、选择性渲染。开发人员可以重写shouldComponentUpdate提高diff的性能
React组件之间的传值
父子组件:父传子 props;子传父:子组件调用父组件中的函数并传参
兄弟:利用redux实现
所有关系都通用的方法:利用Pubsub.js 订阅
setState()为异步的考量
1、保证内部的一致性
因为props是要等到父组件渲染完成 过后才能拿到,也就是说不能同步更新,
state
出于统一性设计成异步
2、性能优化
同步会导致运行阻塞,延迟
3、支持state在幕后渲染
异步可以使state在幕后更新,而不影响你当前旧页面的交互,提神用户体验
React性能优化
1、充分利用shouldComponentUpdate函数,不过前提保证你的组件尽量短小精悍,如果当前组件过于庞大复杂,其实也是很难有优化的操作
2、给DOM遍历上添加唯一的key,注意尽量不要使用index,因为如果你新的DOM中删除了某一个节点,它会重新排列index。导致和原来数据完全不一样,而重新渲染,所以最好使用id什么的来做key值
3、能使用const声明的尽量使用const
4、DOM里少用箭头函数,当然其实要传参时要用还得用,再者,函数bind尽量写在constructor,避免每次render重新bind
5、减少对真实DOM的操作
6、如果使用webpack搭建环境的话 当一个包过大加载过慢时,可分打成多和个包来优化(未测试)
React与vue的对比
相同点
1、都是虚拟DOM的操作实现快速渲染
2、父子、兄弟之间通信相近,都有自己的状态管理器react=>redux, vue=>vuex
3、都是轻量级的应用框架
4、现在vue也渐渐吸收了一些React中的语法,比如JSX语法 类式生命写法等
不同
1、React属于单项数据流--MVC模式,vue则属于双向数据流---MVVM模式
2、react兼容性比vue好,vue不兼容IE8
3、React采用JSX语法,vue采用的是html模板语法
4、vue的css可以有组件的私有作用域。React没有
网友评论