React 基础知识点

2020-02-21  本文已影响0人  阿羡吖

一、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算法

1、把树形结构按照层级分解,只比较同级元素
2、通过给列表结构的每个单个元素添加唯一key值进行区分同层次的子节点的比较
3、React只会匹配相同 class 的component(这里的class指的是组件的名字)
4、合并操作,调用component的setState方法的时候,React将其标记为dirty 到每一个事件循环结束,React检查所有标记dirty的component重新绘制
5、选择性渲染。开发人员可以重写shouldComponentUpdate提高diff的性能

image.png
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没有

上一篇下一篇

猜你喜欢

热点阅读