2013-04-20 4 views
2

У меня есть проблема, которая меня озадачивает в данный момент. У меня есть модель просмотра Durandal, как указано ниже, но значение и другие переменные и функции, когда я просматриваю коды и изменяю их повсюду.Значение этого в модели Durandal вид

Я прокомментировал нижеследующее, так как легче показать различные значения при прохождении кода.

define(['durandal/plugins/router'], function (router) { 

    var _outerRouter = router; 
    var _outerSelf = this; 

    var viewModel = function() { 

     var _self = this; 
     var _router = router; 
     var _searchCriteria = ko.observable(''); 
     var _searchResults = ko.observableArray([]); 
     var _messages = ko.observableArray([]); 

     this.searchCriteria = _searchCriteria; 
     this.searchResults = _searchResults; 
     this.messages = _messages; 

     this.search = function() { 

      // 
      // When called from the view bindings: 
      // > this = viewModel 
      // > _self = _outerSelf = _outerRouter = undefined 
      // > _router = defined 
      // 
      var that = this; 

      // 
      // N.B. I set callback context to the viewModel 
      // 
      var req = $.ajax({ 
       url: '../api/v1/things', 
       dataType: 'json', 
       context: this, 
       data: { 
        searchCriteria: this.searchCriteria() 
       } 
      }) 
      .done(function (results, status, request) { 

       // 
       // When called back: 
       // > this = viewModel 
       // > _self = _outerSelf = _outerRouter = undefined 
       // > _router = defined 
       // 
       this.searchResults.removeAll(); 
       this.messages.removeAll(); 

       // 
       // Now when calling: 
       // > doShowResult = showResult = undefined 
       // > this.showResult = defined (have to use 'this') 
       // > displayMultipleResults = defined 
       // 
       if (results.length == 1) {      
        this.showResult(results[0]); 
       } 
       else { 
        displayMultipleResults(results); 
       } 
      }); 

      function displayMultipleResults(results) { 

       // 
       // When called from ajax.done(): 
       // > this = Window ?!?! 
       // > that = viewModel 
       // > _self = _outerSelf = _outerRouter = undefined 
       // > _router = defined 
       // 
       that.messages.push({ title: 'Found Lots of Things', body: "Please select...blah blah blah", type: 'info' }); 

       for (var i = 0; i < results.length; i++) 
        that.searchResults.push(results[i]); 
      }; 
     }; 

     function doShowResult(result) { 

      // 
      // When called from ajax.done(): 
      // > this = viewModel 
      // > _self = _outerSelf = _outerRouter = undefined 
      // > _router = defined 
      // 
      // and then 
      // 
      // When called from the view bindings: 
      // > this = the bound searchResult object 
      // > _self = _outerSelf = _outerRouter = undefined 
      // > _router = defined 
      // 
      _router.navigateTo('show-my-thing'); 
     } 

     this.showResult = doShowResult; 
    }; 

    return viewModel; 
}); 

А вот мнение, что это связано с:

<div> 
    <div class="container-narrow">  
     <div class="row-fluid"> 
      <div class="span12"> 
       <h3>Search</h3> 

       <p>Enter search criteria...</p> 

       <div class="control-group"> 
        <input type="text" class="input-block-level" placeholder="Criteria" data-bind="value: searchCriteria"/> 
       </div> 

       <div class="pull-right"> 
        <button class="btn btn-primary" data-bind="click: search"> 
         <i class="icon-search icon-white"></i> Search 
        </button> 
       </div> 

      </div> 
     </div> 
     <br /> 

     <!-- ko foreach: messages --> 
     <div class="row-fluid"> 
      <div class="alert" data-bind="css: { 'alert-error': type == 'error', 'alert-info': type == 'info', 'alert-success': type == 'success' }"> 
       <strong data-bind="text: title"></strong> <span data-bind="text: body"></span> 
      </div> 
     </div> 
     <!-- /ko --> 

     <!-- ko foreach: searchResults --> 
     <div class="row-fluid"> 
      <div class="span12 well well-small">     
       <div class="span10 search-result"> 
        <label>Resut:</label> <span data-bind="{text: $data}"></span><br /> 
       </div> 
       <div class="span2">      
        <button class="btn btn-mini btn-success pull-right" data-bind="click: $parent.showResult"> 
         View 
        </button> 
       </div> 
      </div>   
     </div>  
     <!-- /ko --> 

    </div> 
</div> 

Мой главный вопрос, являются:

  1. Каким образом я могу получить доступ _router но не _self (или других переменных (_searchCriteria и т. д.) везде?

  2. Как при выполнении внутри ajax.done(), а значение this равно viewModel, но после того, как оно вступило в displaySearchResult this равно объекту Window?

  3. Когда внутри ajax.done()doShowResult и showResult являются undefined но this.showResult работает отлично, конечно, если this является viewModel то showResult определяется?

  4. К счастью, в этом случае мне нужно только ориентироваться в doShowResult, а _router определяется, когда я звоню как из ajax.done, так и из привязки вида. Но что, если мне нужно получить доступ к значению из модели представления - это не будет доступно, если вызывается из привязки вида, - как я могу изменить привязки или код для поддержки этого (предпочтительно не хакерским способом)?

Заранее благодарим за любой свет, который может пролить на него.

ответ

4

Ключевое слово 'this' ведет себя по-разному в JavaScript к другим языкам, также как и понятие видимой области видимости.

Значение «this» в любой момент времени зависит от контекста вызова функции, к которой вы обращаетесь. Существует четыре разных способа вызова метода, и каждый из них имеет разные последствия для «этого».

  1. Вызов как функция (вызывается именованная функция): this = window (т. Е. Глобальный объект).

    function fName() { }; 
    fName(); // this = window 
    
  2. Призывание как метод (свойство объекта вызывается): это = объект

    var o = {}; 
    o.whatever = function() {}; 
    o.whatever(); // this = o 
    
  3. Invocation в качестве конструктора (с использованием нового ключевого слова): это = новый объект

    var Animal = function() { }; // best practice to capitalise the initial letter of function intended to be called as constructor. 
    var cat = new Animal(); // this = (what will become cat) 
    
  4. Призыва с применить() и вызов() методы: (это = первый из параметров)

    function fName() { }; 
    var obj1 = {}; 
    fName.apply(obj1); // this = obj1 
    fName.call(obj1); // this = obj1 
    
+0

благодарственные за очень ясное объяснение выше - это многое объясняет, особенно в отношении пунктов 2 и 3. Тем не менее, я до сих пор путают о том, как я могу видеть '_router' но а не '_self' во всех функциях ... не могли бы вы помочь в этом? –

Смежные вопросы