javascript - 我是否总是使用 Knockout 映射插件来制作我的 View 模型,从而过度使用它?

标签 javascript mvvm knockout.js knockout-mapping-plugin

我仍在学习 Knockout 的正确用法,我发现自己在设置 View 模型时很快就不再输入 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 的工作中,你是否仍然手动声明 observables,一个一个,或者你是否使用了我使用的 mapping.fromJS 方法?像这样频繁使用映射插件有什么特别的缺点吗?

编辑:

具体例子

In this article , 史蒂夫通过做设置他的 viewModel

var initialData = [ { ... } , { ... } ]; // json from the serializer
var viewModel = {
    gifts : ko.observableArray(initialData)
};

通常,对于这种情况,我也会使用 ko.mapping.fromJS,特别是确保数组中的对象也变成可观察对象。看看他所做的,我的方法似乎有点矫枉过正,增加了一些不必要的开销。

最佳答案

在使用 Knockout 一段时间后,我注意到映射插件有一些额外的选项,可以让您对映射过程进行更精细的控制。

控件类型和生成的属性数量

有多种方法可以实现这一点,我将介绍其中的一些方法,但最终结果是您最终会从映射插件中获得较轻的结果,因为一切都不可观察。

基本上,您将您认为不会改变的所有内容都保留为普通属性,并且仅将您想要观察的特定项目作为可观察对象。

使映射省略某些属性

您可以通过指定诸如 ignoreinclude 之类的内容,使映射插件从最终结果中完全忽略属性。这两者都以相反的方式完成同一件事。

注意:样本来自 knockout.js mapping plugin documentation , 评论是我加的

映射插件参数: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 参数,如下所示。它将从源对象中除指定属性之外的所有属性生成可观察对象。

// 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);
            };
        }
    }
}

订阅、闭包和映射,我的天啊

另一种情况是,如果您希望在结果中包含闭包和订阅。此示例太长,无法完整包含,但它适用于车辆品牌/型号层次结构。如果模型未启用,我希望给定品牌(父)的所有模型(子)都被取消启用,我希望通过订阅来完成。

// 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% 的对象是可观察的。深入研究映射配置选项并创建各种复杂和简单的对象。这个想法是只得到你需要的一切,不多也不少。

关于javascript - 我是否总是使用 Knockout 映射插件来制作我的 View 模型,从而过度使用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7488208/

相关文章:

html - 如何使用离线存储和 Knockout.js 实现 MVVM?

knockout.js - ko.observable 有什么用

javascript - 为什么访问给定位置旁边的元素会出现错误,而访问前一个元素却可以正常工作?

javascript - 计算文件输入的总大小

c# - 使用 MVVM 如何从许多可视组件或选项更新标签?

knockout.js - KnockoutJS - 嵌套数据,加载子项

javascript - 选择前一个父jQuery的 child

javascript - react 将对象添加到对象

c# - IEditableCollectionView 在 CommitEdit 上失去选择

c# - 在 MVVMLight 中关于 ViewModelLocator 正确使用 MEF