React系列知识——ref、生命周期函数、transition动画的使用

React中ref的使用

import React, { Component, Fragment } from "react";
import TodoItem from './TodoItem';
import './TodoList.css'; 
​
class TodoList extends Component {
  constructor(props) {
    super(props)
    this.state = {
      inputValue: '',
      list: []
    }
    this.handleInputChange = this.handleInputChange.bind(this)
    this.handleClick = this.handleClick.bind(this)
    this.handleItemClick = this.handleItemClick.bind(this)
  }
  render() {
    return (
      <Fragment>
        <div>
          <label htmlFor="todoInput">请输入内容: </label>
          <input
            id="todoInput"
            className="container"
            placeholder="todo"
            value={this.state.inputValue}
            onChange={this.handleInputChange}
            ref={(input) => {this.input = input}}
          />
          <button className="add-btn" onClick={this.handleClick}>新增</button>
        </div>
        {/* ref 的使用 */}
        <ul ref={(ul) => {this.ul = ul}}>
          { this.getTodoItem() }
        </ul>
      </Fragment>
    );
  }
  getTodoItem() {
    return this.state.list.map((item, index) => {
      return (
        <TodoItem
          key={index}
          content={item}
          index={index}
          deleteItem={this.handleItemClick}
        />
      )
    })
  }
  handleInputChange(e) {
    const value = this.input.value
    this.setState(() => ({
      // inputValue: e.target.value
      // 使用 ref
      inputValue: value
    }))
    // 相当于
    // this.setState(() => {
    //   return { inputValue: e.target.value }
    // })
  }
  handleClick() {
    // 当 setState 和 ref 共同使用时,可能会出现获取 DOM 节点不及时的问题
    // 可以把获取节点的操作放到 setState 的第二个参数 callback 回调参数中
    // 这样就能正确的获取到节点
    // 在 React 中应尽量减少 ref 的使用去操作 DOM 节点
    // React 的思想是面向数据,数据驱动
    this.setState(() => ({
      list: [...this.state.list, this.state.inputValue],
      inputValue: ''
    }), () => {
      console.log(this.ul.querySelectorAll('div').length)
    })
  }
  handleItemClick(index) {
    this.setState(() => {
      const list = [...this.state.list]
      list.splice(index, 1)
      return { list }
    })
  }
}
​
export default TodoList;

React的生命周期函数

生命周期函数:在某一个时刻组件会自动调用执行的函数。

Initialization

setup props and state

初始化过程,初始化数据,如 props 和 state


Mounting

componentWillMount

↓

render

↓

componentDidMount

componentWillMount在组件即将被挂载到页面的时刻自动执行

componentDidMount在组件被挂载到页面之后自动执行

Updation

props states

componentWillReceiveProps          shouldComponentUpdate

          ↓                          true ↓     ↓ false

shouldComponentUpdate                     ↓     ×

true ↓        ↓ false               componentWillUpdate

     ↓        ×                              ↓

componentWillUpdate                        render

   ↓                                         ↓

render                               componentDidUpdate

   ↓

componentDidUpdate

componentWillReceiveProps:条件:一个组件要从父组件接受参数时执行,执行时刻:只要父组件的render函数被重新执行了,子组件的这个声明周期函数就会被执行。如果这个组件第一次存在与父组件中(初次渲染)不会执行,如果这个组件之前已经存在于父组件中才会执行。

shouldComponentUpdate组件被更新之前会自动执行,应该返回一个布尔值 true / false,false将不再执行后续操作。

componentWillUpdate组件被更新之前会自动执行,但是是在shouldComponentUpdate之后执行,如果shouldComponentUpdate返回true它才会被执行,返回false将不执行

componentDidUpdate组件更新完成之后会被执行


Unmounting

componentWillUnmount

当组件即将被从页面中剔除的时候执行


React生命周期函数的使用场景

shouldComponentUpdate可以用于对渲染性能的优化

父组件进行更新时,子组件没有内容更新,此时父组件的render会被重新执行,子组件也会跟着重新执行render,会造成无意义的render消耗,可以在子组件中使用 shouldComponentUpdate 避免掉不必要的更新。

// shouldComponent可以接受两个参数 nextProps, nextState
shouldComponentUpdate(nextProps, nextState) {
    if (nextProps.content !== this.props.content) {
        return true
    } else {
        return false
    }
}

不建议在 render 函数中发起ajax 请求,因为render会在一系列过程中执行多次,就会发起多次请求,容易造成循环。

componentDidMount 中发起ajax请求获取数据

npm install axios --save
import axios from 'axios';
​
componentDidMount() {
    axios.get('api/todolist').then(() => {
        alert('success')
    }).catch(() => {
        alert('catch error')
    })
}

react-transition-group的使用

安装:

npm install react-transition-group --save
import React, { Component, Fragment } from 'react';
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import './Hello.css';
​
class Hello extends Component {
  constructor(props) {
    super(props)
    this.state = {
      show: true,
      list: ['CSSTransitionGroup']
    }
    this.handleToggle = this.handleToggle.bind(this)
    this.delItem = this.delItem.bind(this)
  }
  render() {
    return (
      <Fragment>
        <TransitionGroup>
          {
            this.state.list.map((item, index) => {
              return (
                <CSSTransition
                  key={index}
                  timeout={1000}
                  classNames='fade'
                  unmountOnExit
                  onEntered={(el) => el.style.color = 'blue'}
                  appear={true}
                >
                  <div>{item}</div>
                </CSSTransition>
              )
            })
          }
        </TransitionGroup>
        <button onClick={this.handleToggle}>add</button>
        <button onClick={this.delItem}>delete</button>
      </Fragment>
    )
  }
  handleToggle() {
    this.setState(() => ({
      show: this.state.show ? false : true,
      list: [...this.state.list, 'CSSTransitionGroup']
    }))
  }
  delItem() {
    this.setState(() => {
      const list = [...this.state.list]
      if(list.length) list.pop()
      return { list }
    })
  }
}
​
export default Hello;
.fade-enter, .fade-appear {
  opacity: 0;
}
.fade-enter-active, .fade-enter-appear {
  opacity: 1;
  transition: opacity 1s ease-in;
}
.fade-enter-done {
  opacity: 1;
}
.fade-exit {
  opacity: 1;
}
.fade-exit-active {
  opacity: 0;
  transition: opacity 1s ease-in;
}
.fade-exit-done {
  opacity: 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值