用Decorator优化React
2018-11-29 本文已影响0人
bb7bb
什么是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
这个插件即可
后话
关于用decorate优化react就到这了。利用修饰器造轮子实际上也是很有艺术的一件事。
最后,我们都需要努力