react 基础知识

react 特点

  • 声名式开发
  • 可以与其他框架并存
  • 组件化
  • 单向流数据
  • 视图层框架
  • 函数式编程
props, state render
state 和 props 中数据改变render函数 执行
父组件的render函数重新执行的时候子组件的render 也会执行
虚拟DOM (js 对象,js 和 js 比较不耗性能, 真实dom 对比比较耗性能 )
1. state数据
2. JSX模版
3. 数据+模版结合,生成真实的DoM,来显示
4. state发生改变
5. 数据+模版结合,生成真实的DOM,替换原始的DOM

缺陷:
数据改变完整替换DOM,非常好性能

解决方案1:

5. 数据+模版结合,生成真实的DOM,并不直接替换原始的DOM
6. 新的DOM (DoucumentFragment) 和原始的DOM做比对,找差异
7. 找出input框发生了变化
8. 只用新的DOM中的input元素,替换掉老的DOM中的input元素

解决方案2:(推荐)

1. state数据 
2. JSX模版 
3· 生成虚拟DOM (虚拟DOM就是一个JS对象,用它来描述真实DOM)
['div', (id: 'abc'}, ['span', t), 'hello world']]
4. 用虚拟DOM生成真实的DOM,来显示
<div id='abc'><span>hello world</span></div>
5. state发生变化 
6. 数据+模版 结合,生成新的虚拟DOM
['div', (id: 'abc'}, ['span', t), 'bye bye']]
7. 比较原始虚拟DOM和新的虚拟DOM的区别,找到区别的内容(提升性能)diff 算法
8. 直接操作DOM,改变span中的内容


render() {
const { content, test }= this.props;
// JSx-> createELemnt-> 虚拟DOM (JS对象) ->真实的DOM
return (<div><span>item</span></div>
return React.createELement('div", {}, React.createELement('span', {}, 'dddd')
}

优点:
1. 性能提升
2. 它能跨端应用得以实现
虚拟DOM diff (原始虚拟DOM和新的虚拟DOM的区别比对)
1. 同层比对
2. 不能用 key={index}作为key 值 (item,用它本身做key值)
3. setdata 可以吧多次比对合并成一次比对
监听获取输入同步 react ref (获取dom) (onChange)
<input className="search-input fl" type="search" onChange={this.handlechange.bind(this)}  onKeyUp={this.onKeyup.bind(this)}/>


handlechange(event) {
    let val = event.target.value.replace(/^\s+|\s+$/g,"");
    this.setState(() => ({ keyword: val }));
};

onKeyup(e) {
    if(e.keyCode === 13) {
        if (this.state.keyword.length > 1) {
            this.setState(() => ({page: 1 }));
            this.getData()
        }
    }
}


<form className="form-menu" ref="form">
<label><i>*</i>作品名称:</label>
<input className="input-border" defaultValue={title} ref="title"/>
<button type="button" className="submit" onClick={this.submitFun.bind(this)}>{this.state.modalTitle}</button>
</form>

 // 表单提交
    submitFun() {
        const {formData} = this.state;
        const { title } = this.refs;
        const inputData = {};
        if (title.value.length < 2) {
            this.setState(() => ({hint: '作品名称不能少于2个字符' }));
        } else {
            inputData.title =  title.value;
            if(formData.id) {
                inputData.id = formData.id;
                this.edit(BACKEND_UPDATA_URL, inputData);
                return 
            }
            this.setState(() => ({formData: inputData }));
            this.add(BACKEND_CREATE_URL, inputData)
        }
    };

  父组件调用子组件中的方法

    子组件

    import React from 'react';

    export default class Message extends React.Component {
    constructor(props) {
    super(props);
    this.state = {
        message: ''
    }

    };
    componentDidMount() { 
    this.props.onRef(this) 
    } 
    reminding(ms) {
    this.setState(() => ({ message: ms}));
        setTimeout(() => { 
            this.setState(() => ({ message: '' })) 
        },3000 )
    }
    render() { 
        return (
            <p className={this.state.message.length > 0 ? "message-hint-active" : 'message-hint' }>{this.state.message}</p>
            ) 
        }
    }


    父组件:

     <Message onRef={this.onRef} />

    onRef = (ref) => {
        this.Message = ref
    }

    that.Message.reminding(res.data.message)
setSate 函数的方法(异步方法)
this.setSate((prevState) => ({
    list: [...prevState.list, inputValue],
    inputValue: ' '
}), () => {
    // 回调方法执行完数据存储后执行可以获取刚才同步的数据
})
生命周期函数(组件自动调用的函数)
1. constructor()
    es6 语法自带构造函数

组件挂载

1、componentWillMount()

    页面挂载之前调用,以后组件更新不调用,只调用一次,此时可以修改state。

2、 render()

    react最重要的步骤,创建虚拟dom,进行diff算法,更新dom树都在此进行。此时就不能更改state了。

3、componentDidMount()

    组件挂载之后调用,组件渲染之后调用,只调用一次。


组件更新

componentWillReceiveProps(nextProps)
    组件接受新的props时调用。
    组件从父组件接收参数(第一次不会执行)
    父组件render 重新执行了才被执行

   props 更新                  state 更新

    1. componentWillUpdata(nextProps, nextState) // 需要返回一个bloo (true, false)

        组件更新之前时才调用,此时可以修改state

    2. shouldComponentUpdate(nextProps, nextState)

        组件更新之前时才调用,(componentWillUpdata 之后执行)
        react性能优化非常重要的一环。组件接受新的state或者props时调用,我们可以设置在此对比前后两个props和state是否相同,如果相同则返回false阻止更新,因为相同的属性状态一定会生成相同的dom树,这样就不需要创造新的dom树和旧的dom树进行diff算法对比,节省大量性能,尤其是在dom结构复杂的时候

    3. render()
        组件渲染

    4. componentDidUpdate()

        组件更新完成后调用,此时可以获取dom节点。

组件卸载:

componentWillUnmount()

    组件将要卸载时调用,一些事件监听和定时器需要在此时清除。



默认设置:

1、getDefaultProps()

    设置默认的props,也可以用dufaultProps设置组件的默认属性.

2、getInitialState()

    在使用es6的class语法时是没有这个钩子函数的,可以直接在constructor中定义this.state。此时可以访问this.props
React css 动画效果
<p className={this.state.message.length > 0 ? "show" : 'hind' }>{this.state.message}</p>

显示隐藏
  .show {transition: all 1s ease-in;opacity: 0;}
  .hind {transition: all 1s ease-in; opacity: 1;}

显示隐藏变色 

  .show {opacity: 1;transition: all 1s ease-in;}
  .hide {animation: hide-item 2s ease-in forwards;}
  @keyframes hide-item {
  0% {
       opacity: 1;color: red;
  }
  50% {
  opacity: 0.5;color: green;

  }
  100% {
  opacity: 0;color: blue;
  }

第三方动画模块 react-transition-group
地址: https://reactcommunity.org/react-transition-group/
redux

基本原则:

1. store 是唯一的
2. 只有store能够改变自己的内容 
2. reducer: 必须是纯函数 (给定固定的函数,就会有固定的输出,不会有任何副作用(不能对参数进行修改,)

核心API

createStore             创建store
store.dispath           更新上传 
store.getState          获取
store.subscribe         改变时触发
组件:
子组件直接调用父组件方法 

    <div onClick={(index) => {this.props.handlechange(index)}}></div>
  1. 普通组件 (逻辑和渲染都在一个组件)
  2. ul组件 (少量的逻辑 + 无状态组件)
  3. 容器组件(逻辑)
  4. 无状态组件 (渲染不加逻辑处理)
//  无状态组件
import React, { Component } from 'react';
const TodoListUI = (props)=> {
return (
<div> 
<div><Inputvalue {props. inputValue) 
onChange {props.handLeInputChange}/>
<Button onclick={props.handleBtnclick) /div>
</div)
中间件
redux-thunk

1. store -> action 可以是函数和对象
2. store -> dispath 方法的升级

redux-sage
posted @ 2020-04-22 09:52  libenzheng  阅读(83)  评论(0)    收藏  举报