角度控制器和巴贝尔

时间:2016-08-01 15:25:25

标签: javascript angularjs this babeljs

我正在使用ES6功能创建一个Angular应用程序,所以我使用Babel来转换JS。我决定不使用ES6模块,因此我使用es2015而不是常规es2015-script预设。

问题在于Babel编译箭头功能的方式。我使用Angular的控制器作为符号,如此

angular.module('appControllers')
.controller('StoryController', ['StoryProvider', (StoryProvider)=>{
    this.plaintext='test plain';
}]);

此代码已转换为

var _this = this;

angular.module('myControllers')
.controller('StoryController', ['StoryProvider', function (StoryProvider)             
{
    _this.plaintext = 'test plain';
}]);

因此this的范围完全错误且绑定无效。当我手动将编译代码更改为

angular.module('myControllers')
.controller('StoryController', ['StoryProvider', function (StoryProvider)             
{
    var _this = this;
    _this.plaintext = 'test plain';
}]);

一切正常。

为什么Babel以这种方式设置中间_this变量?还有另一个Babel预设可以正确处理吗?我应该使用ES6模块吗?我首先遇到了与此问题angular 1.5 component and babel中描述的问题相同的问题,这就是我使用es2015-script预设的原因。

2 个答案:

答案 0 :(得分:1)

好的,这里有几种方法

1)使用ES6 class

class StoryController{
    constructor(StoryProvider){
        this.plaintext='test plain';
        this.StoryProvider=StoryProvider;
    }
}

这增加了大约1k的辅助函数,正如您所看到的,我们需要在构造函数中保存注入的依赖项。

2)摆脱主控制器定义中的箭头功能,仅在方法中使用它。

之类的东西
function StoryController(StoryProvider){
    this.plaintext='test plain';
    this.asyncTest=()=>{
        setTimeout(()=>{
            console.log(this.plaintext);
        }, 100);
    };
}

这转化为一个不错的

function StoryController(StoryProvider) {
    var _this = this;

    this.plaintext = 'test plain';

    this.asyncTest = function () {
        setTimeout(function () {
            console.log(_this.plaintext);
        }, 100);
    }; 
}

正确定位_this变量。

答案 1 :(得分:0)

您答案中的替代解决方案似乎有效,但我想提供问题的答案:

  

为什么Babel以这种方式设置中间_this变量?

首先,一些背景资料。根据{{​​3}}:

  

在箭头函数之前,每个新函数都定义了它自己的这个值(在构造函数的情况下是一个新对象,在严格模式函数调用中是未定义的,如果函数被称为“对象方法”则是上下文对象,等等) 。事实证明,这是一种面向对象的编程风格。

要理解胖箭头功能的一点是,它们不仅仅是创建函数的更短语法 - 它们创建了一个函数而没有它自己的词法范围。这意味着当您在胖箭头功能中使用this.plaintext时(在非严格模式下),this未按预期在控制器上设置,但在全局对象

现在关于巴贝尔。

Babel正在做最好让你的转换代码行为与源完全一样(这就是重点吗?)所以当它必须使用ES5兼容的函数声明重写你的胖箭头函数时,它必须拉入从某个地方引用全局对象。因此,在前一行中,它将对它的引用抓取为_this并在fat-arrow函数中使用它,因为它认为这是你想要的。

正如您在问题中所展示的那样,最简单的解决方案是首先用标准函数声明替换fat-arrow函数,这样您就可以有一个词法范围来挂起。