React 学习笔记

声明式的开发 React
命令式的开发 Jquery


单项数据流
父组件可以给子组件传值,但子组建不能改变这个值
单项数据流的好处:
实际是为了开发时方便,不容易遇到坑,方便测试。
一个父子建有五个子组件,假如没有单项数据六的概念,任何一个子组件把父组件给改变了(删除等),其余的几个组建也会受到影响。


视图层框架

数据层框架

函数式编程

TodoList.js中的文件

import React, { Component,Fragment } from 'react';
import './style.css'
import TodoItem from './TodoItem';
import Test from './Test';

// import { Component } from 'react';
// import React from 'react'
// const Component = React.Component


// Fragment 代替div


class TodoList extends Component {

  constructor(props){
    super(props); //继承
    // 组建的状态
    this.state = {
      inputValue: '',
      list: ['1','2'],
    }
    this.handleInputChange = this.handleInputChange.bind(this)
  }

  

  //在组件即将被挂载在页面的时刻自动执行
  componentWillMount(){
    console.log('componentWillMount')
  }

  render() {
    return (

      <Fragment>
        <div>
          {/*下面时一个input框*/}
          {
            //下面时一个input框
          }
          <label htmlFor="insertArea">输入内容</label>
          <input
            id='insertArea'
            className='input'
            value={this.state.inputValue} type=""
            onChange={this.handleInputChange}
            ref={(input) => {this.input = input}}
          />
          <button onClick={this.handleBtnClick.bind(this)}>提交</button>
        </div>
        <ul ref={(ul) => {this.ul=ul}}>
          { this.getTodoItem() }
        </ul>
        <Test content={ this.state.inputValue } />
      </Fragment>
    );
  }

  

  

  //在组件挂载在页面的完毕时刻自动执行
  componentDidMount(){
    console.log('componentDidMount')
  }

  //组件更新之前,他会自动被执行==你的组件需要被更新?决定组件是否要被更新
  shouldComponentUpdate(){
    console.log('shouldComponentUpdate')
    return true
  }

  //组件被更新之前,他会自动执行,但是他在shouldComponent之后被执行,、
  //如果shouldComponentUpdate返回true才执行
  //如果shouldComponentUpdate返回false不执行
  componentWillUpdate(){
    console.log('componentWillUpdate')
  }
  //组件更新完成之后会被执行
  componentDidUpdate(){
    console.log("componentDidUpdate")
  }

  getTodoItem() {
    return this.state.list.map((item,index)=>{
      return (
        <div key={index}>
          <TodoItem
            content={item}
            index={index}
            deleteItem = {this.handleItemDelete.bind(this)}
          />
          {/*<li
            key={index}
            onClick={this.handleItemDelete.bind(this,index)}
            dangerouslySetInnerHTML={{ __html:item }}
          >
          </li>*/}
        </div>

      )
    })
  }

  handleInputChange(e){
    console.log(this.input.value)

    //react最新版本的改变状态的写法
    const value = e.target.value
    this.setState( () => ({
      inputValue: value
    }))


    // this.setState({
      // inputValue: e.target.value
    // })
  }
  handleBtnClick(){
    // 异步
    this.setState( (prevState) => ({
      // prevState之前的数据
      list: [...prevState.list,prevState.inputValue],
      inputValue: ''
    }),() => {
      console.log(this.ul.querySelectorAll('div').length)
    })

    // console.log(this.ul.querySelectorAll('div').length)

    // this.setState({
      // list: [...this.state.list,this.state.inputValue],
      // inputValue: ''
      // })
  }
  handleItemDelete(index){
    // immutable
    // state 不允许我们做任何改变
    // const list = [...this.state.list]

    this.setState((prevState)=>{
      const list = [...prevState.list];
      list.splice(index,1)
      return {list}
    })


    // this.setState({
      // list: list
    // })
  }

}

export default TodoList;

TodoItem.js

import React,{ Component } from 'react';
import PropTypes from 'prop-types';

class TodoItem extends Component{

  constructor(props){
    super(props)
    this.handleClick = this.handleClick.bind(this)
  }

  // 使用 shouldComponentUpdate优化性能,不需要input输入值改变就重新渲染子组件,做个判断
  shouldComponentUpdate(nextprevProps,nextState){
    console.log(nextprevProps,nextState)
    if(nextprevProps.conent !== this.props.conent){
      return true
    }else{
      return false
    }
  }

  render(){
    const { content, test } = this.props
    return (

      <div
        key={this.props.index}
        onClick={this.handleClick}
      >
        {/*React.createElement('div',{},'item')*/}
        { test } - { content }
      </div>
    )
  }

  //当一个组件从父组件接收了参数
  //只要父组件的render函数执行了,子组件的这个生命周期函数就会被执行
  //如果这个组件第一年存在于父组件中,不会执行
  //如果这个组件之前已经存在于父组件中,会被执行
  componentWillReceiveProps(){
    console.log("child componentWillReceiveProps")
  }

  //当这个组件即将被从页面剔除的时候,会被执行
  componentWillUnmount(){
    console.log("child componentWillUnmount")
  }

  handleClick(){
    const { deleteItem,index } = this.props
    deleteItem(index)
  }
}

//属性校验==要求父组件给子组件传值的校验
// isRequired 必须要传值
TodoItem.propTypes = {
  test: PropTypes.string.isRequired,
  content: PropTypes.oneOfType([PropTypes.string,PropTypes.number]),
  deleteItem: PropTypes.func,
  index: PropTypes.number,
}


TodoItem.defaultProps = {
  test: 'hello world'
}

export default TodoItem

Test.js

import React,{ Component } from 'react';

class Test extends Component{
  render () {
    return <div>{ this.props.content }</div>
  }
}


export default Test

propTypes 与 DefaultProps
//属性校验==要求父组件给子组件传值的校验
TodoItem.propTypes = {
content: PropTypes.string,
deleteItem: PropTypes.func,
index: PropTypes.number
}
// 默认复制
TodoItem.defaultProps = {
test: 'hello world'
}


Props,State与render函数
当数据发生变化时,页面就跟着发生变化
当组件的state或者props发生改变的时候,render函数就会重新执行;
当父组件的render函数被运行时 ,他的子组件的render都将被重新运行一次

什么是虚拟DOM?


原始操作的方法
1. state 数据
2. jsx 模板
3. 数据 + 模板 结合,生成真是的DOM,来显示
4. state 发生改变
5. 数据 + 模板 结合,生成真是的DOM,替换原始的DOM

缺陷:
第一次生成了一个完成额DOM片段
第二次又生成了一个完成的DOM片段
第二次的DOM替换第一次的DOM,非常好性能


1. state 数据
2. jsx 模板
3. 数据 + 模板 结合,生成真是的DOM,来显示
4. state 发生改变
5. 数据 + 模板 结合,生成真是的DOM,并不直接替换原始的DOM
6. 新的DOM和原始的DOM作比对,找差异
7. 找出input框发生了变化
8. 只用新的DOM中的input元素,替换掉老的DOM中的input元素

缺陷:
性能的提升并不明显

React引入的虚拟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 发生变化
<div id="abc"><span>bye bye</span></div>
6. 数据+模板 生成虚拟DOM(极大的提升了性能)
['div',{id:'abc'},['span',{},"bye bye"]]
7. 比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中的内容(极大的提升了性能)
diff
setState 异步算法,提高了比对。
8. 直接操作DOM,改变span中的内容

有点:
1.性能提升了
2.他使得跨端应用得以实现。 React Native


//深入了解虚拟DOM

//虚拟DOM中的DIff算法


//React 中的ref的使用

React中的生命周期函数
//生命周期函数指在某一时刻组件会自动执行的函数

//在组件即将被挂载在页面的时刻自动执行
componentWillMount(){
  console.log('componentWillMount')
}

//在组件挂载在页面的完毕时刻自动执行
componentDidMount(){
console.log('componentDidMount')
}

//组件更新之前,他会自动被执行==你的组件需要被更新?
shouldComponentUpdate(){
  console.log('shouldComponentUpdate')
  return true
}

//组件被更新之前,他会自动执行,但是他在shouldComponent之后被执行,、
//如果shouldComponentUpdate返回true才执行
//如果shouldComponentUpdate返回false不执行
componentWillUpdate(){
  console.log('componentWillUpdate')
}
//组件更新完成之后会被执行
componentDidUpdate(){
  console.log("componentDidUpdate")
}

//当一个组件从父组件接收了参数
//只要父组件的render函数执行了,子组件的这个生命周期函数就会被执行
//如果这个组件第一年存在于父组件中,不会执行
//如果这个组件之前已经存在于父组件中,会被执行
componentWillReceiveProps(){
  console.log("child componentWillReceiveProps")
}

//当这个组件即将被从页面剔除的时候,会被执行
componentWillUnmount(){
  console.log("child componentWillUnmount")
}

原文地址:https://www.cnblogs.com/sklhtml/p/9518171.html