2016-03-10 91 views
3

我遇到了knockout.js組件和require.js。 到目前爲止,這工作得很好,但我正在努力處理以下問題。從其包含viewmodel訪問組件viewmodel

比方說,我有我的組件的一個實例在一個非常簡單的HTML頁面:

<div id="exams"> 
    <databound-exam-control></databound-exam-control> 
</div> 

從包含視圖模型:

require(['knockout', 'viewModel', 'domReady!'], function (ko, viewModel) { 
    ko.components.register('databound-exam-control', { 
     viewModel: { require: 'databound-exam-control-viewmodel' }, 
     template: { require: 'text!databound-exam-control-view.html' } 
    }); 

    ko.applyBindings(new viewModel()); 
}); 

我想獲得孩子視圖模型內容後當我點擊一個按鈕時保存頁面的所有數據。

現在我只是想顯示顯示在標籤的父/子的ViewModels:

<div> 
    <pre data-bind="text: childViewModel()"></pre> 
</div> 

隨着包含視圖模型的幫助:

function childViewModel() { 
     var model = ko.dataFor($('databound-exam-control').get(0).firstChild); 
     return ko.toJSON(model, null, 2); 
}; 

我得到的調用ko.dataFor在下面的錯誤,可能是因爲該網頁無法完全呈現:

除非指定'寫入'選項,否則無法將值寫入ko.computed。如果您想讀取當前值,請不要傳遞任何參數。

是不是這樣?或者我在這裏完整地忽略了這一點?

任何幫助表示讚賞。

+0

我想說,設置你的主視圖模型來跟蹤你創建的子模型可能會更好。作爲一個人爲的例子,你可以看看:https://jsfiddle.net/timh06/91n3m25t/ 也可以不用'ko.dataFor'來查看'ko.contextFor',它應該可以訪問綁定元素的上下文。 – Timh

回答

3

父視圖模型和子組件之間的通信的更簡單的方法是通過使用參數。

  • 創建父視圖模型一個新的觀察特性,如childViewModel = ko.observable()
  • 把它作爲參數傳遞給子組件<databound-exam-control params= "{modelForParent: childViewModel}">注意孩子視圖模型內部的參數將被稱爲modelForParent,並在父視圖模型將被稱爲childViewModel在視圖模型構造器組件
  • ,在你的databound-exam-control-viewmodel.js腳本,您會收到的參數作爲構造函數的唯一參數。因此,如果您的構造函數如下所示: function SomeComponentViewModel(params)您可以訪問參數params.modelForParent
  • 使用該參數將您需要的任何信息從子組件傳遞到父組件,例如:params.modelForParent(createdChildViewModel)

現在,父組件可以使用childViewModel可觀察值訪問子視圖模型。

使用觀測僅僅是一種可能性。你可以用其他方式做到這一點。例如,將回調傳遞爲參數,並在viewmodel構造函數中執行該回調以將任何您想要的內容返回給父級。我有時使用以下模式:

  • 在父創建一個寄存器API的回調,像這樣:registerApi = function(api) { config.childApi = api }
  • 通這個作爲參數傳遞給在子視圖模型構造器子組件
  • 調用回調傳遞孩子API

這樣,我可以通過存取權限的子組件這樣顯示的API:config.childApi.aMethosExposedByTheChild()

IMPO rtant注意:您必須考慮到,由於子組件異步加載,子項公開的信息不能直接使用。除非您需要立即使用它,否則這不是問題。例如,就你而言,它看起來像是在組件加載並且用戶與它進行交互之後從子視圖模型獲得信息,所以這不是問題。如果您需要儘快訪問它,則可以使用輪詢或更好地向子項公開延期(示例實現:$.Deferred),以便它可以解決此問題,讓母公司模型知道它已經可用。當子視圖模型依賴通過AJAX調用加載外部資源(例如加載下拉列表或服務器上存在的其他信息)時,也會發生這種情況。

另一個我不喜歡的選擇是父視圖模型包含整個shild視圖模型並將其作爲參數傳遞,所以父視圖模型完全控制了子視圖模型。很明顯,這個解決方案不允許組件負責其自己的視圖模型,所以父視圖模型和chld組件之間存在緊密的耦合,這是不可取的。

+0

感謝您的詳細解答,我會盡力回覆您。我也嘗試使用[knockout-postbox](https://github.com/rniemeyer/knockout-postbox)。 –