簡體   English   中英

我是否過度使用Knockout映射插件總是用它來做我的viewmodel?

[英]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.observableko.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省略某些屬性

您可以通過指定ignoreinclude類的內容使映射插件完全從最終結果中省略屬性。 這兩者都以相反的方式完成了同樣的事情。

注意:樣本來自knockout.js映射插件文檔 ,我添加了評論

Mapping Plugin參數: 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM