2016-08-01 80 views
1

我創建了一個使用ES6功能的Angular應用程序,所以我使用Babel來轉換JS。我決定不使用ES6模塊,所以不是使用常規的es2015預設,而是使用es2015-script角控制器As和babel

問題在於Babel編譯箭頭函數的方式。我採用了棱角分明的controllerAs符號,像這樣

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

這段代碼transpiled到

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'; 
}]); 

它一切正常。

爲什麼巴貝爾設置中間變量_this這種方式?有沒有另一個巴貝爾預設來正確處理這個問題?我應該使用ES6模塊嗎?我遇到的問題與本期第angular 1.5 component and babel中描述的相同,這就是爲什麼我使用了es2015-script預設。

+0

用常規的'function()'替換箭頭函數有幫助,但我真的很喜歡用''this'詞法。 –

+1

這段代碼似乎沒有任何問題;這裏使用箭頭函數是錯誤的。控制器被設計成擁有自己的'this'。箭頭函數正在做它設計要做的事情(詞法綁定'this'值(不綁定它自己的this','arguments','super'或'new.target')。),這不是管制員期望如何申報。 – Claies

+0

「但我真的很喜歡用詞法這個。」你不能,除非你想使用'$ scope' –

回答

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); 
    }; 
} 

這transpiles一個不錯的

function StoryController(StoryProvider) { 
    var _this = this; 

    this.plaintext = 'test plain'; 

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

其作用域正確的_this變量。

0

在你的答案的替代解決方案似乎是有效的,但我想提供一個答案的問題:

爲什麼巴別塔的中間變量_this這樣設置?

首先是一些背景資料。據MDN

直到箭頭的功能,每一個新的功能定義了自己的這個值(在構造函數的情況下,一個新的對象,不確定的嚴格模式函數調用,上下文對象,如果該功能被稱爲一個「對象方法「等)。事實證明,這是一種面向對象的編程風格。

瞭解關於脂肪箭頭功能的事情是,他們不只是創造一個功能更短的語法 - 他們創造一個功能沒有它自己的詞法範圍。這意味着當您在胖箭頭功能(非嚴格模式下)內使用this.plaintext時,this未設置在您期望的控制器上,而是在全局對象上設置。

現在關於巴別塔。

Babel在做最好的事情是讓你的編譯代碼完全像源代碼一樣(這就是要點吧?)所以當它必須使用兼容ES5的函數聲明來重寫fat-arrow函數時,從某處引用全局對象。因此,在前面的一行中,它會將其引用爲_this,並將其用於胖箭頭函數中,因爲它認爲這就是您想要的。


正如你在你的問題表明,最簡單的辦法是擺在首位的標準功能的聲明,以取代脂肪箭頭功能,這樣你就會有一個詞彙範圍掛東西。