深入react技术栈记录(一)

1. react.Component

React 的所有组件都继承自顶层类 React.Component。它的定义非常简洁,只是初始化了
React.Component 方法,声明了 props、context、refs 等,并在原型上定义了 setState 和
forceUpdate 方法.

2. 无状态函数

示例代码如下:

function Button({ color = 'blue', text = 'Confirm' }) {
  return (
    <button className={`btn btn-${color}`}>
      <em>{text}</em>
    </button>
  );
}

无状态组件只传入 props 和 context 两个参数;也就是说,它不存在 state,也没有生命周
期方法,组件本身即上面两种 React 组件构建方法中的 render 方法。不过,像 propTypes 和
defaultProps 还是可以通过向方法设置静态属性来实现的。
在适合的情况下,我们都应该且必须使用无状态组件。无状态组件不像上述两种方法在调用
时会创建新实例,它创建时始终保持了一个实例,避免了不必要的检查和内存分配,做到了内部
优化。

3.props与state

state 与 props 是 React 组件中最重要的概念。如果顶层组件初始化 props,那么 React 会向下
遍历整棵组件树,重新尝试渲染所有相关的子组件。而 state 只关心每个组件自己内部的状态,
这些状态只能在组件内改变。把组件看成一个函数,那么它接受了 props 作为参数,内部由 state
作为函数的内部参数,返回一个 Virtual DOM 的实现。

4. 生命周期

componentWillMount 方法会在 render 方法之前执行,而componentDIdMount方法会在render之后执行,分别代表了渲染前后的时刻。

如果我们在 componentWillMount 中执行 setState 方法,会发生什么呢?组件会更新 state,
但组件只渲染一次。因此,这是无意义的执行,初始化时的 state 都可以放在 this.state。
如果我们在 componentDidMount 中执行 setState 方法,又会发生什么呢?组件当然会再次更
新,不过在初始化过程就渲染了两次组件,这并不是一件好事。但实际情况是,有一些场景不得
不需要 setState,比如计算组件的位置或宽高时,就不得不让组件先渲染,更新必要的信息后,
再次渲染。

shouldComponentUpdate 是一个特别的方法,它接收需要更新的 props 和 state,让开发者增加
必要的条件判断,让其在需要时更新,不需要时不更新。因此,当方法返回 false 的时候,组件
不再向下执行生命周期方法。

深入react技术栈记录(一)

 

 

 5. 计算DOM的尺寸

React 中使用 DOM 最多的还是计算 DOM 的尺寸(即位置信息)。我们可以提供像 width 或
height 这样的工具函数:

function width(el) {
    const styles = el.ownerDocument.defaultView.getComputedStyle(el, null);
    const width = parseFloat(styles.width.indexOf('px') !== -1 ? styles.width : 0);
    const boxSizing = styles.boxSizing || 'content-box';
    if (boxSizing === 'border-box') {
        return width;
    }
    const borderLeftWidth = parseFloat(styles.borderLeftWidth);
    const borderRightWidth = parseFloat(styles.borderRightWidth);
    const paddingLeft = parseFloat(styles.paddingLeft);
    const paddingRight = parseFloat(styles.paddingRight);
    return width - borderRightWidth - borderLeftWidth - paddingLeft - paddingRight;
}        

6. react中绑定原声事件

componentDidMount 会在组件已经完成安装并且在浏览器
中存在真实的 DOM 后调用,此时我们就可以完成原生事件的绑定。比如:

import React, { Component } from 'react';
class NativeEventDemo extends Component {
    componentDidMount() {
        this.refs.button.addEventListener('click', e => {
        this.handleClick(e);
    });
}
handleClick(e) {
    console.log(e);
}
componentWillUnmount() {
    this.refs.button.removeEventListener('click');
}
render() {
    return <button ref="button">Test</button>;
    }
}    

值得注意的是,在 React 中使用 DOM 原生事件时,一定要在组件卸载时手动移除,否则很
可能出现内存泄漏的问题。而使用合成事件系统时则不需要,因为 React 内部已经帮你妥善地处
理了。

7. 使用原生事件时冒泡的问题

用 reactEvent.nativeEvent.stopPropagation() 来阻止冒泡是不行的。阻止 React 事件冒泡的行为只能用于 React 合成事件系统
中,且没办法阻止原生事件的冒泡。反之,在原生事件中的阻止冒泡行为,却可以阻止 React 合成事件的传播。

消除冒泡例子, 点击二维码外的位置收起二维码

componentDidMount() {
    document.body.addEventListener('click', e => {
    if (e.target && e.target.matches('div.code')) { // code是二维码的className
        return;
    }
    this.setState({
    active: false,
    });
    });
}    

8.



上一篇:android-更改“ DialogPreference”的突出显示颜色(按钮颜色)


下一篇:在Android中使用自定义样式创建TimePickerDialog