[英]Am I overusing the Knockout mapping plugin by always using it to do my viewmodel?
我還在學習Knockout的正確使用方法,我發現自己很快就擺脫了在設置我的viewmodel時輸入ko.observable
而只是定義了一個對象文字並通過映射插件傳遞它
var viewModel = ko.mapping.fromJS(data);
或者至少,將所有數據填充到viewModel上的屬性中,就像這樣
var viewModel = {
... events etc ... ,
"data": ko.mapping.fromJS(data)
}
說實話,我一直這樣做的主要原因是必須重復輸入ko.observable
和ko.observableArray
。 我只是想弄清楚這是否是一個好的方法,如果有任何缺點,一起刪除特定的var x = ko.observable()
聲明。 此外,我正在加載所有這些,而不是響應任何ajax調用等,從我可以看出,這是映射插件的設計目的。
在使用knockout的工作中,你是否仍然手動逐個聲明observable,或者你使用了我使用的mapping.fromJS方法? 像這樣經常使用映射插件有什么特別的缺點嗎?
編輯:
在本文中 ,Steve通過這樣做來設置他的viewModel
var initialData = [ { ... } , { ... } ]; // json from the serializer
var viewModel = {
gifts : ko.observableArray(initialData)
};
通常,我只是在這種情況下使用ko.mapping.fromJS
,特別是為了確保數組中的對象也被轉換為可觀察對象。 看看他做了什么,我的做法似乎有些過度,並增加了一些不必要的開銷。
在使用Knockout一段時間后,我注意到映射插件有一些額外的選項,可以讓您對映射過程進行更精細的控制。
有幾種方法可以實現這一點,我將討論一些,但最終結果是你最終得到了映射插件的更輕的結果,因為一切都是不可觀察的。
基本上你把你認為不會改變的一切都留下來作為一個普通的屬性,只從你想要觀察的特定項目中做出可觀察的。
mapping
省略某些屬性 您可以通過指定ignore
或include
類的內容使映射插件完全從最終結果中省略屬性。 這兩者都以相反的方式完成了同樣的事情。
注意:樣本來自knockout.js映射插件文檔 ,我添加了評論
include
以下代碼段將省略源對象中除通過include
參數傳入的屬性之外的所有屬性 。
// specify the specific properties to include as observables in the end result
var mapping = {
// only include these two properties
'include': ["propertyToInclude", "alsoIncludeThis"]
}
// viewModel will now only contain the two properties listed above,
// and they will be observable
var viewModel = ko.mapping.fromJS(data, mapping);
ignore
如果只想省略源對象中的某些屬性 ,請使用ignore
參數,如下所示。 除了指定的屬性外,它將從源對象中的所有屬性創建可觀察對象。
// specify the specific properties to omit from the result,
// all others will be made observable
var mapping = {
// only ignore these two properties
'ignore': ["propertyToIgnore", "alsoIgnoreThis"]
}
// viewModel will now omit the two properties listed above,
// everything else will be included and they will be an observable
var viewModel = ko.mapping.fromJS(data, mapping);
如果你需要包含屬性,但你不認為它們需要被觀察(無論出於何種原因),那么映射插件可以提供幫助。
copy
如果您希望映射插件只是簡單地復制普通屬性而不使它們可觀察,請使用此參數,如下所示。
// tell the mapping plugin to handle all other properties normally,
// but to simply copy this property instead of making it observable
var mapping = {
'copy': ["propertyToCopy"]
}
var viewModel = ko.mapping.fromJS(data, mapping);
如果您希望100%控制映射過程中創建的內容, 包括在對象中放置閉包和訂閱的功能 ,那么您需要使用“創建”選項。
這是一個示例,我將數據從ajax調用映射到具有results
屬性的對象。 我不想要任何可觀察的東西,我只想要一個簡單的生成屬性,它將由對象上的其他簡單屬性組成。 也許不是最引人注目的例子,但它展示了功能。
var searchMappingConfig = {
// specific configuration for mapping the results property
"results": {
// specific function to use to create the items in the results array
"create": function (options) {
// return a new function so we can have the proper scope/value for "this", below
return new function () {
// instead of mapping like we normally would: ko.mapping.fromJS(options.data, {}, this);
// map via extend, this will just copy the properties from the returned json element to "this"
// we'll do this for a more light weight vm since every last property will just be a plain old property instead of observable
$.extend(this, options.data);
// all this to add a vehicle title to each item
this.vehicleTitle = this.Year + "<br />" + this.Make + " " + this.Model;
}, this);
};
}
}
}
另一種情況是,如果您想在結果中使用閉包和訂閱。 此示例太長,無法完整地包含在內,但它適用於車輛品牌/模型層次結構。 如果模型未啟用,我希望取消啟用給定make(父)的所有模型(子項),並且我希望通過訂閱完成此操作。
// here we are specifying the way that items in the make array are created,
// since makes has a child array (Models), we will specify the way that
// items are created for that as well
var makesModelsMappingConfig = {
// function that has the configuration for creating makes
"create": function (options) {
// return a new function so we can have the proper
// scope/value for "this", below
return new function () {
// Note: we have a parent / child relationship here, makes have models. In the
// UI we are selecting makes and then using that to allow the user to select
// models. Because of this, there is going to be some special logic in here
// so that all the child models under a given make, will automatically
// unselect if the user unselects the parent make.
// make the selected property a private variable so it can be closure'd over
var makeIsSelected = ko.protectedComputed(false);
// expose our property so we can bind in the UI
this.isSelected = makeIsSelected;
// ... misc other properties and events ...
// now that we've described/configured how to create the makes,
// describe/configure how to create the models under the makes
ko.mapping.fromJS(options.data, {
// specific configuration for the "Models" property
"Models": {
// function that has the configuration for creating items
// under the Models property
"create": function (model) {
// we'll create the isSelected as a local variable so
// that we can flip it in the subscription below,
// otherwise we wouldnt have access to flip it
var isSelected = ko.protectedComputed(false);
// subscribe to the parents "IsSelected" property so
// the models can select/unselect themselves
parentIsSelected.current.subscribe(function (value) {
// set the protected computed to the same
// value as its parent, note that this
// is just protected, not the actual value
isSelected(value);
});
// this object literal is what makes up each item
// in the Models observable array
return {
// here we're returning our local variable so
// we can easily modify it in our subscription
"isSelected": isSelected,
// ... misc properties to expose
// under the item in the Model array ...
};
}
}
}, this);
};
}
};
總而言之,我發現你很少需要100%的對象傳遞給插件,而你很少需要100%的可觀察對象。 深入了解映射配置選項並創建各種復雜和簡單的對象。 我們的想法是只獲得您需要的一切,無論是更多還是更少。
我給你的建議也是另一個問題,我剛才在https://stackoverflow.com/questions/7499133/mapping-deeply-hierarchical-objects-to-custom-classes-using-knockout-mapping-plug上回答。
您使用映射插件的原因是合理的,也是我使用的插件。 為什么要輸入比你更多的代碼?
根據我的淘汰經驗(全部4個月),我發現我手動做的越少,讓淘汰程序做他們的事情,我的應用程序似乎運行得越好。 我的建議是先嘗試最簡單的方法。 如果它不能滿足您的需求,請查看簡單方法如何做“事情”並確定必須更改以滿足您的需求。
艾倫,我最近在Knockout.js的學習經歷與你的相似。 我們使用來自服務器的深層次對象圖,我已經定義了顯式的可實例化視圖模型函數,它們保留了它的基本結構。
我首先將每個屬性顯式定義為相關視圖模型上的可觀察對象,但很快就失控了。 此外,切換到使用映射插件的一個主要原因是我們必須經常將圖表的Ajax帖子發送回服務器,並將其與持久版本合並,然后在服務器上驗證,以便眾多屬性可以修改更改和集合,並將新實例作為Ajax結果返回,必須將其與客戶端表示重新合並。 這變得非常困難,並且映射插件通過允許指定用於解析添加/刪除/更新的標識符以及將更新的圖重新映射到原始圖上來幫助大量時間。
它還通過使用子視圖模型的“創建”選項幫助創建原始圖形。 在每個視圖模型構造函數中,我接收對父視圖模型的引用以及用於構造子視圖模型的數據,然后創建進一步的映射選項以從傳入的子數據創建孫子。
我最近發現的唯一(輕微)缺點是,在這個問題中詳細說明,當執行ko.mapping.toJSON時,它不會掛鈎到您在視圖模型的原型上定義的任何toJSON覆蓋,以便排除屬性從序列化。 我已經能夠通過在取消映射中指定忽略選項來解決這個問題,正如Ryan Niemeyer在該帖子中所建議的那樣。
總而言之,我肯定會堅持使用映射插件。 Knockout.js規則。
一個更簡單但更有幫助的附加組件可能是淘汰數據預測
目前,它不處理js到viewmodel映射,但它處理很好的視圖模型到JS映射。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.