用Decorator优化React

作者: bb7bb | 来源:发表于2018-11-29 14:01 被阅读0次

    什么是decorator

    decorator是ES6的一个新特性,可以修改class的属性

    @test
    class Person {
      //do something
    }
    function test(tartget){
      traget.prototype.name = 'xiaoming';
      traget.prototype.sayName = function (){console.log(this.name)}
    }
    var p = new Person();
    p.sayName();  //'xiaoming'
    
    

    通过decorator,这样就可以做到一个类的优雅嵌套

    多个decorator

    @test1
    @test2
    @test3
    @test4
    class Person {
      //do something
    }
    

    实际上多个decorator会从上到下依次进入函数,然后再从下往上依次执行。想象一下高阶组件的嵌套可能会比较好理解一些

    优化React代码

    实际上根据它的用法,我们可以联想到React高阶组件

    //往往我们习惯于这样去写高阶组件,但是一旦高阶组件多,则会引起书写的不美观
    class MyComponent extends React.Component{
    }
    export default withRoute(connect(MyComponent))
    
    //实际上我们可以这么写
    @withRoute
    @connect
    export default class MyComponent extends React.Component{
    }
    

    而且修饰器不仅用于class,我们还可以用于类里面的方法

    @withRoute
    export default class MyComponent extends React.Component{
      constructor() {
        //将组件的this绑定给函数
        this.handleClick = this.handleClick.bind(this)
      }
    
      @log
      handleClick() {
      }
    }
    
    function log(target, name, descriptor) {
      const oldValue = descriptor.value;
      const obj = { ...descriptor };
      obj.value = function (...arg) {
        const result = oldValue.apply(this, arg);
        console.log(`name: ${name} arg: ${arg} target:${JSON.stringify(target)} oldValue:${oldValue} value:${JSON.stringify(result)}`);
        return result;
      };
      return obj;
    }
    

    这里我们用组件示例,该方法可以使得每次触发handleClick时都可以打印出信息。但是如果细心的朋友就会注意到,我们的handleClick并不是用箭头函数写的。这里也是值得注意的一点,修饰器不能直接修饰箭头函数或者匿名函数,尽管这是类的方法。原因是因为函数会存在提升,实际代码如下

    export default class MyComponent extends React.Component{
      @log
      handleClick = () => {
      }
    }
    export default class MyComponent extends React.Component{
      @log
      handleClick = function () {
      }
    }
    //以上两种方法都不可以使用修饰器
    export default class MyComponent extends React.Component{
      @log
      this.handleClick;
      handleClick = () => {
      }
    }
    

    Decorator用在react上的奇淫技巧

    实际上我们可以自定义所有组件

    // MyReact.js
    import React from 'react';
    
    export default function myComponet(target) {
      Object.setPrototypeOf(target, React.Component);
      // B 的实例继承 A 的实例
      Object.setPrototypeOf(target.prototype, React.Component.prototype);
      return target;
    }
    
    
    // page.js
    import myComponent from './MyReact'
    
    @myComponent
    class Page {
      render(){
        return <p>我是组件<p>
      }
    }
    

    这样做的好处就是,我们可以在所有的组件里面添加自己的一些东西。比如埋点。当然,其实不使用修饰器其实也可以做到这点,但是这种写法会更为简洁。

    现在可以使用该语法吗

    实际上这还只是个提案,babel对这个需要安装特殊的插件才可以支持转义该语法babel-plugin-transform-decortors-legacy。因此在使用该语法的时候,可能还需要慎重选择。如果要调试修饰器这个语法,我只能推荐,先去Babel转义成ES5语法,然后再在chrome上调试。转译时记得添加babel-plugin-transform-decortors-legacy这个插件即可

    image.png

    后话

    关于用decorate优化react就到这了。利用修饰器造轮子实际上也是很有艺术的一件事。

    最后,我们都需要努力

    相关文章

      网友评论

        本文标题:用Decorator优化React

        本文链接:https://www.haomeiwen.com/subject/cjtaqqtx.html