2013-05-16 24 views
3

我正在玩一個基於杜蘭達的SPA,並遵循他們的'觀點'和'視圖模型'的約定,基本功能工作正常。即使用somepage.html & somepage.js純粹的UI相關的javascript在Durandal視圖中出現在哪裏?

但是,當添加更多交互式UI元素(例如可摺疊的手風琴或信息彈出窗口)時,處理這些事件的JavaScript應該放在哪裏?它不'聞到'的權利,把它放在somepage.js viewmodel文件 - 這是爲... 查看模型

從最佳實踐角度來看,在我的somepage.html文件中有一個腳本塊會更好嗎?例如。

<section> 
    <!- html markup and data-binding goes here> 
</section> 

<script type="text/javascript"> 
    <!-- UI-only Javascript goes here> 
</script> 

或者還有更好的方法嗎?

+2

HTML的JavaScript應該由**綁定**或**小部件**處理。如果你想要一個淘汰賽的手風琴,谷歌它。在某些情況下,彈出窗口可以由視圖模型處理。 – Tyrsius

回答

3

我一直在爲此而苦苦掙扎,我同意將視圖相關的東西放入viewModel中。我需要做的是你要說的是attach a delegated event handler - 這不能像使用自定義綁定或小部件那樣完成。

一位同事和我想出的最佳解決方案是從viewModel傳播viewAttached事件,並在「視圖文件」中偵聽事件。

使用一個名爲 「真棒」 作爲一個例子來看,我們正在使用的命名約定是這樣的:

  • 視圖模型 - 的ViewModels/awesome.js
  • 查看 - 視圖/ awesome.html
  • 查看文件 - 視圖/ awesome.html.js

這是我們正在做的簡化版本。

的ViewModels/awesome.js:

define([ 
    "durandal/app", 
    "durandal/system", 

    // require the view file; note we don't need a reference to it, 
    // we just need to make sure it's loaded 
    "views/myView.html" 
], 

function (app, sys) { 
    var viewModel = { 
     // whatever 
    }; 

    viewModel.viewAttached = function(view) { 
     // Create a namespace for the event 
     var eventNamespace = sys.getModuleId(viewModel) 
      .replace("viewmodels", "") 
      .replace("/", "."); 

     // This will evaluate to 'awesome.viewAttached' 
     var eventName = eventNamespace + ".viewAttached"; 

     // Trigger the event and pass the viewModel and the view 
     app.trigger(eventName, viewModel, view); 
    }; 

    return viewModel; 
}); 

的意見/ awesome.html.js:

define([ 
    "durandal/app" 
], 

function (app) { 
    var module = { 
     viewAttached: function(viewModel, view) { 
      // do your thing! make sure any selectors you use use the view as the parent selector, 
      // because you're not guaranteed that your view is in the DOM (only that it's attached 
      // to its parent). 
      var $submit = $("#submit", view); 
     } 
    }; 

    // wire-up 
    app.on("awesome.viewAttached", module.viewAttached); 

    // export 
    return module; 
}); 

希望有所幫助。

+0

我仍然不得不圍繞委託事件處理程序的工作方式,但這似乎是遵循現有結構約定的優雅解決方案。謝謝! –

+0

委派的事件處理程序允許您在父節點上附加事件,然後父節點可以爲子節點選擇事件。例如如果您的容器中裝滿了按鈕,而不是爲每個按鈕附加一個「單擊」事件處理程序,則可以在容器上附加一個事件處理程序,該處理程序將偵聽來自子按鈕的任何「單擊」事件。非常便利! – gerrod

3

您的純GUI GUI元素應該通過html數據屬性綁定到UI。例如,一個引導手風琴將有以下HTML (Bootstrap Documentation here)

<div class="accordion" id="accordion2"> 
    <div class="accordion-group"> 
    <div class="accordion-heading"> 
     <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseOne"> 
     Collapsible Group Item #1 
     </a> 
    </div> 
    <div id="collapseOne" class="accordion-body collapse in"> 
     <div class="accordion-inner"> 
     Anim pariatur cliche... 
     </div> 
    </div> 
    </div> 
....... 

和引導文件JavaScript文件在頁面底部引用。

1

viewAttached是一個相當危險的小東西......它試圖把所有的JS代碼放在那裏......但它並不理想。所述一個小怪癖我發現的是,在嵌套視圖模型

父 第1步(兒童1) 步驟2(兒童2)

家長交換機(child1 < - >的child2)

如果父級操縱子視圖(從子級1切換到子級2)viewAttached將無法在子級上正確觸發(DOM在該時間點尚不可用),並且由於父級已連接,所以不會運行viewAttached父母要麼!

因此突然發現所有的JS模塊都會停止工作,然後必須爲需要由外部JS修改的元素執行ko customBindings。