React初探

react首先是类似一个组件库的js文件,包含view和controller的库。

react组件根据平台本身可以映射成原生控件和web dom。

采用babel的编译工具将jsx转换成js来描述对应的元素。

 

无状态组件:使用无状态函数构建的组件成为无状态组件,只传入props,context两个参数,不存在state,没有生命周期方法。无状态组件在调用时不会创建新实例,避免了不必要的检查和内存分配。

 

react-dom:findDOMNode(ReactComponent) 获取真正的DOM元素,返回该react组件对应的DOM节点。

 

react-dom:unstable_renderSubtreeIntoContainer: ReactMount._renderSubtreeIntoContainer(parentComponent,

nextElement, container, callback)。将目标元素插入指定节点container

render: ReactMount._renderSubtreeIntoContainer(null, nextElement, container, callback)。 两者的区别在于是否传入父节点。

 

React.cloneElement: 给指定组件传递props

React.children: 获取当前组件的子组件

 

合成事件:

    事件委派:React并不会把事件处理函数直接绑定到 真实的节点上,而是把所有事件绑定到结构的最外层,使用一个统一的事件监听器,这个事件监 听器上维持了一个映射来保存所有组件内部的事件监听和处理函数。当组件挂载或卸载时,只是 在这个统一的事件监听器上插入或删除一些对象;当事件发生时,首先被这个统一的事件监听器 处理,然后在映射里找到真正的事件处理函数并调用。

   自动绑定:React 组件中,每个方法的上下文都会指向该组件的实例,即自动绑定 this 为当前组件。或者利用箭头函数自动获取当前this。

       事件捕获:会优先调用结构树最外层的元素上绑定的事件监听器,然后依 次向内调用,一直调用到目标元素上的事件监听器为止。

       事件冒泡:则与事件捕获的表现相反,它会从目标元素向外传播事件,由内而外直到最外层。

React的合成事件则并没有实现事件捕获,仅仅支持了事件冒泡机制。

 

非受控组件:一个表单组件没有 value props(单选按钮和复选框对应的是 checked prop) 时,就可以称为非受控组件。

      它是一种反模式,它的值不受组件自身的 state 或 props 控制。通常, 需要通过为其添加 ref prop 来访问渲染后的底层 DOM 元素。

 

classnames样式库:classNames({ 'btn': true, 'btn-pressed': this.state.isPressed, 'btn-over': !this.state.isPressed && this.state.isHovered,});

 

CSS Modules: 能最大化地结合现有 CSS 生态和 JavaScript 模块化能力,其 API 非常简洁。 发布时依旧编译出单独的 JavaScript 和 CSS 文件。

         现在,webpack css-loader 内置 CSS Modules 功能。

启用 CSS Modules 的代码如下:

// webpack.config.js

css?modules&localIdentName=[name]__[local]-[hash:base64:5]

加上 modules 即为启用,其中 localIdentName 是设置生成样式的命名规则。

使用了 CSS Modules 后,就相当于给每个 class 名外加了 :local,以此来实现样式的局部化。如果我们想切换到全局模式,可以使用 :global 包裹

对于样式复用,CSS Modules 只提供了唯一的方式来处理——composes 组合。

/* components/Button.css */ .base { /* 所有通用的样式 */ }

/* settings.css */.primary-color { color: #f40; }

.primary {composes: base; composes: $primary-color from './settings.css'; /* primary 其他样式 */}

如果不想频繁地输入 styles.**,可以使用 react-css-modules 库。它通过高阶组件的形式来 避免重复输入 styles.**。可以这么写---styleName="root"

使用 CSS Modules,容易使用 :global 去解决特殊情况,使用 react-css-modules 可写成 <div className="global-css" styleName="local-module"></div>,

这种形式轻松对应全局和局部;

 

跨级组件通信:

在子组件定义 static contextTypes = {color: PropTypes.string} ,通过this.context.color获取顶层组件的color属性

在顶层组件定义 static childContextTypes = {color: PropTypes.string},  实现方法 getChildContext() {return{color: 'red'}

 

没有嵌套关系的,那只能通过可以影响全局的一些机制去考虑。import { EventEmitter } from 'events';

在 componentDidMount 事件中,如果组件挂载完成,再订阅事件;当组件卸载的时候,在 componentWillUnmount 事件中取消事件的订阅。

 

对于广义的 mixin 方法,就是用赋值的方式将 mixin 对象里的方法都挂载到原对象上,来实 现对对象的混入。

 

React 在使用 createClass 构建组件时提供了 mixin 属性,mixins: ['xxx','xxx'],

在不同的 mixin 里实现两个名字一样的普通方法,这会造成冲突。因此, 在 React 中是不允许出现重名普通方法的 mixin。

如果是 React 生命周期定义的方法,则会将各个模块的生命周期方法叠加在一起顺序执行。

 

使用我们推荐的 ES6 classes 形式构建组件时,它并不支持 mixin。

对于实现 mixin 方法来说,这就没什么不一样了。但既然讲到了语法糖,就来讲讲另一个语 法糖 decorator,正巧可以用来实现 class 上的 mixin。

core-decorators 库为开发者提供了一些实用的 decorator,其中实现了我们正想要的 @mixin。 下面解读一下其核心实现:

function handleClass(target, mixins) {

  if (!mixins.length) { throw new SyntaxError(`@mixin() class ${target.name} requires at least one mixin as an argument`); }

  for (let i = 0, l = mixins.length; i < l; i++) {
    // 获取 mixins 的 attributes 对象
    const descs = getOwnPropertyDescriptors(mixins[i]);

    // 批量定义 mixins 的 attributes 对象

    for (const key in descs) {

      if (!(key in target.prototype)){

        defineProperty(target.prototype, key, descs[key]);

      }

    }

  }

}

源代码十分简单,它将每一个 mixin 对象的方法都叠加到 target 对象的原型上 以达到 mixin 的目的。这样,就可以用 @mixin 来做多个重用模块的叠加了。

这里用了getOwnPropertyDescriptor 和 defineProperty 这两个方法,

好处在于 defineProperty 这个方法,也就是定义与赋值的区别,定义是 对已有的定义,赋值则是覆盖已有的定义。所以说前者并不会覆盖已有方法,但后者会。

 

高阶组件:

  属性代理是常见高阶组件的实现方法

  const MyContainer = (WrappedComponent) =>

  class extends Component {---这里将Component替换成WrappedComponent就实现了反向继承,除了一些静态方法,包括生命周期,state,各种function,我们都可以得到。

我们同时可以以此进行hijack(劫持),也就是控制它的render函数。在render()中调用superRender(),然后通过在外层嵌套的方式改变原有渲染

    handleClick = () => {console.log('clicked');}

    render() {

      const otherProps = {handleClick:this.handleClick}
      return <WrappedComponent {...this.props}  ref={instanceComponent => this.instanceComponent = instanceComponent}/>;

    }

  }

  export default MyContainer//--->这是一个hoc组件

 

  class MyComponent extends Component { ... }

  export default MyContainer(MyComponent);

  高阶组件可以看做是装饰器模式(Decorator Pattern)在React的实现。即允许向一个现有的对象添加新的功能,同时又不改变其结构,属于包装模式(Wrapper Pattern)的一种

ES7中添加了一个decorator的属性,使用@符表示,上面一行可以改写成@MyContainer

  可以在hoc高阶组件中自定义事件,并通过props传递下去,在hoc高阶组件中使用ref,获取当前被包含组件的引用ref

 

上一篇:wepy 小程序开发(Mixin混合)


下一篇:java,android获取系统当前时间