Backbone + ES2015 Class

在 ES2015 下使用 Backbone,需要一点点小技巧。

小型项目还是 Backbone 用起来比较舒心,所以写着写着又开始用它了。这次还用到 ES2015 和 Babel,于是疑问就来了:怎么在 ES2015 下使用 Backbone 呢?

普通用法

Backbone 自带 .extend() 方法,在早期的蛮荒岁月可以帮我们方便的创建各种子类。

var MyView = Backbone.View.extend({
  events: {

  },
  tagName: 'div',
  initialize: function () {

  }
});

以前这样确实很方便,代码也很好读。但是 ES2015 引入了新的 Class 规范,写出来是这样婶儿的:

class MyView extends Backbone.View {
  // 其实不能这样写
  tagName: 'div'
  events: {

  }
  // 上面这样写是不对的
  constructor() {

  }
}

这个时候问题来了。ES2015 不支持直接声明类属性,也就是上面代码中的 tagNameevents,是不能这样写的。因为它实际上只是重新包装了原型继承那一套东西,所以上面的代码实际上等效于:

MyView = function () {

}
MyView.prototype = new Backbone.View();
MyView.prototype.tagName = 'div';
MyView.prototype.events = {

};

这样的结果,不同实例间实际在共享方法和属性,包括 tagNameevents。如果是简单对象,比如字符串和数字,用 = 赋值还好;如果是复杂对象,比如数组,就很容易出问题。

Backbone 1.0 之前也会有这个问题,但是忘记从哪个版本开始就修复了。

新的用法

想要在 ES2015 中继续 Backbone 当然也是可以的。目前看来有三种方式:

  1. 把属性转化为方法。Backbone 对属性的处理都是委托给 _.result(),所以属性和方法的效果是一样的。
  2. 继续使用 MyClass.prototype.someProp = 'value';
  3. 将初始化对象放在构造函数中。

我个人比较喜欢第三种方法,因为它更接近之前的写法,而且结合 Babel、Webpack 等编译打包工具,也可以做到私有。

class MyView extends Backbone.View {
  constructor(init) {
    super(_.extend(init, {
      events: {

      },
      tageName: 'div'
    });
  }
}

未来,ES2016

ES2016 中引入了很重要的 Decorators 概念,顾名思义,它会显式的告诉运行时下面是些什么东西,那么运行时自然也就可以按照对应的规则去处理。

@props({
  tagName: 'div',
  events: {

  }
})
class MyView extends Backbone.View {
  constructor(init) {
    super(init);
  }
}

参考文章

本篇内容主要参考自以下两篇:

作者: meathill

爱编程,爱旅游,爱吐槽。 今年的目标是完成并运营至少一个 Side Project。 《Electron + Vue 实战开发》龟速创作中……

欢迎吐槽,请勿装死

This site uses Akismet to reduce spam. Learn how your comment data is processed.