2015-07-13 3 views
2

У меня возникла проблема с областью «this» при использовании ES6.'this' scope with ES6 and Knockout

Вот ссылка на мой original and transpiled code с BabelJS.

При вызове функции для удаления элемента из массива область действия «это» не определена.

Как я могу сделать это, чтобы сделать это без переопределения этого (let self = this)?

"use strict"; 
 

 
var _createClass = (function() { 
 
    function defineProperties(target, props) { 
 
    for (var i = 0; i < props.length; i++) { 
 
     var descriptor = props[i]; 
 
     descriptor.enumerable = descriptor.enumerable || false; 
 
     descriptor.configurable = true; 
 
     if ("value" in descriptor) descriptor.writable = true; 
 
     Object.defineProperty(target, descriptor.key, descriptor); 
 
    } 
 
    } 
 
    return function(Constructor, protoProps, staticProps) { 
 
    if (protoProps) defineProperties(Constructor.prototype, protoProps); 
 
    if (staticProps) defineProperties(Constructor, staticProps); 
 
    return Constructor; 
 
    }; 
 
})(); 
 

 
function _classCallCheck(instance, Constructor) { 
 
    if (!(instance instanceof Constructor)) { 
 
    throw new TypeError("Cannot call a class as a function"); 
 
    } 
 
} 
 

 
var Point = (function() { 
 
    function Point() { 
 
    var _this = this; 
 

 
    _classCallCheck(this, Point); 
 

 
    this.myArray = ko.observableArray([1, 2, 3, 4]); 
 
    this.removeFromArrayWithArrowFunction = function(value) { 
 
     _this.myArray.remove(value); 
 
    }; 
 
    } 
 

 
    _createClass(Point, [{ 
 
    key: "removeFromArray", 
 
    value: function removeFromArray(value) { 
 
     this.myArray.remove(value); 
 
    } 
 
    }]); 
 

 
    return Point; 
 
})(); 
 

 
ko.applyBindings(new Point());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<span data-bind="text: ko.toJSON(myArray)"></span> 
 
<h2>Issues with this scoping when using a regular Function</h2> 
 
<ul data-bind="foreach: myArray"> 
 
    <li> 
 
    <a href="#" data-bind="text: $data, click: $parent.removeFromArray"></a> 
 

 
    </li> 
 
</ul> 
 

 
<h2>Works as expected using an arrow function</h2> 
 
<ul data-bind="foreach: myArray"> 
 
    <li> 
 
    <a href="#" data-bind="text: $data, click: $parent.removeFromArrayWithArrowFunction"></a> 
 

 
    </li> 
 
</ul>

+1

Это на самом деле не проблема ES6, вы связывание 'click' событие метода объекта. Вы теряете контекст «этого». Вам необходимо привязать метод к родительскому объекту. –

+0

Спасибо @JeffMercado. Любая рекомендация о том, как ее достичь? –

+2

sro предоставляет решение ES6. В противном случае используйте любой из подходов, описанных здесь (http://stackoverflow.com/questions/10737494/context-of-this-when-triggering-method-on-root-from-child). –

ответ

1

Если вы используете ViewModel функции непосредственно в ваших привязок, вы теряете контекст this, как объяснил Джефф Меркадо. Arrow functions capture the this value of the enclosing context, поэтому, если вы используете обозначение функции стрелки, вам не нужно беспокоиться о var self = this.

Меняем следующее:

removeFromArray(value) { 
    this.myArray.remove(value); 
} 

В:

removeFromArray = (value) => { 
    this.myArray.remove(value); 
} 

И он должен работать нормально.

See babel

+5

Пожалуйста, добавьте объяснение к вашему решению, в частности, что вы используете предложение для ES7. Это не ES6. Кроме того, ваше решение в основном то, что сделал OP с 'this.removeFromArrayWithArrowFunction = value => {this.myArray.remove (value);}'. –

+1

Вы правы @FelixKling. Я пробовал это на местном уровне, и это не сработало, так как я не использую экспериментальные функции Babel. Любые другие варианты? –

+1

То, что уже сделал ОП, задав функцию внутри конструктора. –