React 一些知识点

326 阅读7分钟

一、前言:

React的主要内容:

二、React的一些注意的知识点

  • 1、serviceWorker用于离线情况下可以访问
  • 2、pwa === Progressive web application 渐进式web应用。根据manifest.json来访问
  • 3、React 16以上版本,使用Fragment 占位符,就不用外层再包裹一层div,比如:
<Fragment>
    <div>xxx</div>
    <ul>xxxx</ul>
</Fragment>
  • 4、react中的响应式设计思想和事件绑定
  • 5、class 类中就有一个constructor构造函数。组件在创建时,第一个执行的函数就是constructor函数。
  • 6、immutable state不允许做任何改变
  • 7、jsx写注释的方法
{/* xxxx */}
{
    // 下面是一个input框
}
  • 8、在jsx中,希望可以对标签内容不进行转译,需要使用到dangerouslySetInnerHTML进行设置,比如:
return (
    <li 
      key={index} 
      onClick={this.handleItemClick.bind(this, index)}
      dangerouslySetInnerHTML={{__html: item}}
    >
    </li>
)
  • 9、在jsx中,样式要用className来定义css的名字,防止和class类冲突
  • 10、在jsx中,label的for标签要替换为htmlFor,然后使用label的for属性来绑定到input上,如以下代码:
  <label htmlFor="insertArea">输入内容</label>
  // 把光标放在label上,就会自动聚焦到input上。
  <input
    id="insertArea"
    className='input'
    value={this.state.inputValue}
    onChange={this.handleInputChange.bind(this)}
  />
  • 11、react衍生的思考
    • (1)、声名式开发:不用直接操作dom,对比于命令式开发(jquery,原生js都是直接操作dom)
    • (2)、可以与其他框架并存。
    // 在html文件
    <body>
        <div id="root"></root> // 这里挂载的是react代码。
        <div>123123</div> // 这里可以挂载其他框架比如vue、angular、jquery的代码
    </body>
    
    • (3)组件化
      • 【1】、组件的定义:通过class.Component来定义组件
      • 【2】、组件: 首字母大写的,组件是树状结构,父组件通过属性向子组件传值。通过父组件向子组件传递一个方法,子组件调用这个方法间接的来操作父组件的方法,从而实现子组件和父组件的通信。
    • (4) 单向数据流
      • 【1】、父组件可以向子组件传值,但是子组件不能去改变这个值。
    • (5) 视图层框架
    • (6) 函数式编程
      • [1]、好处:维护起来比较容易;给自动化测试带来很大的便捷性;
  • 12、react扩展工具:React developer tools
  • 13、propTypes与defaultProps
    • propTypes对组件接收过来的属性做类型校验使用
      TodoItem.propTypes = {
        test: PropTypes.string.isRequired,
        content: PropTypes.string,
        deleteItem: PropTypes.func,
        index: PropTypes.number
      }
      
    • defaultProps 可以在里面定义组件传过来的默认值
  • 14、props、state与render函数
    • 当组件的state或者props发生改变的时候,render函数就会重新执行。
    • 当父组件的render函数被运行时,它的子组件的render都将被重新运行一次
  • 15、react中的虚拟dom
    • 虚拟dom就是一个js对象,用它来描述真实的dom
    • 用js生成一个js对象比js生成一个dom的代价比较小。因为js直接生成dom需要调用createElementById等属性,所以性能消耗比较高。(减少了对正式dom的创建和对比,直接对比的是js对象,所以性能发生了极大的改进)
    • 虚拟dom的底层原理:
    1、state数据
    2、jsx模版
    3、数据+模版生成虚拟dom(虚拟dom就是一个js对象,用它来描述真实dom)(损耗了性能)。
    ['div', {id: 'abc'}, ['span', {}, 'hello world']]
    4、用虚拟dom的结构生成真实dom来显示
    <div id="abc"><span>hello world</span></div>
    5、state发生变化
    6、数据+模版生成新的虚拟dom(极大的提升了性能)
    ['div', {id: 'abc'}, ['span', {}, 'bye bye']]
    7、比较原始虚拟dom和新的虚拟dom的区别,找到区别中是span的内容(极大的提升了性能)
    8、直接操作dom,改变span中的内容。
    
    • jsx -> createElement -> 虚拟dom(js对象)-> 真实的dom
    return <div>item</div>
    等价于
    return React.createElement('div', {}, 'item')
    
    • 虚拟dom带来的好处
    1、提升了性能
    2、它使得跨端应用得以实现,React Native
    
    • 虚拟dom中的diff算法
    1、同层虚拟dom的比对算法,如果最上层的发生了改变,就不会继续对比了,直接用新的替换掉旧的
    2、在循环的过程中,最好不要用index值做key值来进行标识,因为当key值发生变化的时候,index就发生了变化,从而使key值不唯一,增加对比的难度。要使用稳定的值作为key值。
    

虚拟dom中的同层比对算法。在进行虚拟dom的对比的时候,会先生成一个一样的虚拟dom,然后同层进行对比,当第一层的虚拟dom改变的时候,下面所有的虚拟dom都要被重新渲染,然后替换掉。虽然会增加多余的dom的渲染,但是这样可以简化dom的对比算法。

  • 16、react中的ref

    • 可以获取页面中dom元素(尽量不要用ref,在做动画的时候可能会不得不用到)
    <input
        id="insertArea"
        className='input'
        value={this.state.inputValue}
        onChange={this.handleInputChange}
        ref={(todoInput) => { this.input = todoInput}}
        // ref在这里是一个回调函数,返回一个数值
    />
    handleInputChange() {
        // const value = e.target.value
        const value = this.input.value
        // 这里就可以直接使用ref的引用了。
        this.setState(() => {
          return {
            inputValue: value
          }
        })
    }
    
    • ref使用经常遇到的一个问题
    handleBtnClick() {
        this.setState((prevState) => ({
          list: [...prevState.list, prevState.inputValue],
          inputValue: ''
        }), () => {
            console.log(this.ul.querySelectorAll('div').length)
            // 这里要写在setState的回调函数里面,因为setState是一个异步函数。
        })
        console.log() // 写在这里,会发现setState没运行完就执行了。
    }
    
  • 17、react中的生命周期函数

    • 生命周期函数指在某一个时刻组件会自动调用执行的函数。
    • initialization // 在state和props被改变,初始化时使用
    • mounting---componentWillMount() // 在组件即将被挂载到页面的时刻自动执行
    • mounting---render() // 在组件挂载在页面时执行
    • mounting---componentDidMount() // 组件被挂载到页面之后,自动被执行
    • 以上2个生命周期将在v17.0之后启用,取而代之的是getDerivedStateFromProps、getSnapshotBeforeUpdate这2个生命周期。
    • updation 当数据发生变化的时候,页面的更新会被执行。
    • updation---shouldComponentUpdate() // 组件被更新之前,他会自动被执行,含义是你的组件需要被更新吗?返回boolean类型,true则执行后面的,否则不执行,
    • updation---componentWillUpdate() //组件被更新之前,它会自动执行,但是他在shouldComponentUpdate之后被执行。shouldComponentUpdate返回true才会执行,否则不会被执行。
    • updation---componentDidUpdate() // 组件更新完成之后,它会被执行
    • updation---componentWillReceiveProps() // 一个组件要从父组件接收参数,如果这个组件第一次存在于父组件中,不会执行,如果这个组件之前已经存在于父组件中,才会执行。
    • unmounting---componentWillUnmount() // 当这个组件即将被从页面中剔除的时候会被执行。
  • 18、在react中做性能提升

    • (1)、利用shouldComponentUpdate生命周期做性能优化
    shouldComponentUpdate(nextProps, nextState) {
        if (nextProps.content !== this.props.content) { // 如果传过来的内容和当前内容不同,则需要做数据的更新即render
            return true
        } else {
            return false
        }
    }
    

    // 利用生命周期中shouldComponentUpdate的方法,先提前判断数据有没变化,再做比较,再看下是否要继续执行下去,从而可以避免过多不必要的render.

    • (2)、将函数的作用域绑定都统一写在constructor函数中,这样保证整个函数的作用域绑定只会执行1次,可以避免组件的多次渲染
    constructor(props) {
        super(props)
        this.handleClick = this.handleClick.bind(this) // 作用域的绑定
    }
    
    • (3)、setState,是一个异步函数,可以把多次的操作搞成1次来做,降低数据改变的频率。
    • (4)、react的底层使用了虚拟dom的概念,还有同层对比和虚拟值来提升虚拟dom的比对速度,从而提升react的性能。
  • 19、在componentDidMount中做ajax数据的请求。

    componentDidMount() {
        axios.get('/api/todolist').then((res) => {
          console.log(res.data)
          this.setState(() => {
            return {
              list: [...res.data]
            }
          })
        }).catch(() => {
          alert('error')
        })
    }
    
  • 20、使用react-transition-group实现动画

    <TransitionGroup>
      {
        this.state.list.map((item, index) => {
          return (
            <CSSTransition
              timeout={1000}
              classNames='fade'
              unmountOnExit
              onEntered={(el) => { el.style.color='blue'}}
              appear={true}
              key={index}
            >
              <div>{item}</div>
            </CSSTransition>
          )
        })
      }
    </TransitionGroup>
    
  • 21、在使用css3做样式animation的时候,使用forwards可以让动画停留在最后一帧

    animation: hide-item 2s ease-in forwards;
    
  • 22、redux

    • (1)、Redux = Reducer + Flux
    • (2)、redux 工具: redux devtools
    • (3)、设计和使用的三个原则:
      • 【1】、store是唯一的
      • 【2】、只有store能够改变自己的内容
      • 【3】、Reducer必须是纯函数数据(纯函数指的是给定固定的输入,就一定有固定的输出,而且不会有任何的副作用)
      • 【4】、Redux核心API
        • <1>、createStore 可以创建一个store
        • <2>、store.dispatch 可以派发action,action会传递给store
        • <3>、store.getState 可以帮助获取store的所有内容
        • <4>、store.subscribe 可以订阅store的改变
    • (4)、使用Redux-thunk中间件进行ajax请求
    • (5)、什么是Redux中间件? 首先来看Redux工作流程 首先React Components就是View相当于借书的人,发出了Action Creators借书这个行为,然后通过dispatch去订阅Store(相当于图书管理员),Store需要借助Reducers这个记录本,去记录放在哪里,拿到数据后,就返回给Store.Store再把State给到React Component. 而中间件,就是在Dispatch这个过程中,加入进来对Store进行修改最后返回数据给View.