Knockout.js 映射忽略

Posted

技术标签:

【中文标题】Knockout.js 映射忽略【英文标题】:Knockout.js mapping ignore 【发布时间】:2013-12-26 14:41:04 【问题描述】:

我们正在 .NET MVC 4 上使用 knockout.js 和 knockout.mapping.js。假设我有这样的 JSON:


    "deliveryPointType": "0",
    "deliveryPointTypes": [
        
            "id": 0,
            "text": "Pridėti rankiniu būdu"
        ,
        
            "id": 1,
            "text": "Siųsti visiems regiono objektams"
        
    ],
    "showRegionSelection": false,
    "showDeliveryPointSelection": true,
    "regionId": "",
    "userHasRegions": "False",
    "propertyNames": 
        "deliveryPointTypeName": "Pridėti rankiniu būdu"
    ,
    "initialMaterials": [
        
            "quantity": 0,
            "materialTypeId": "",
            "propertyNames": ,
            "validMaterial": true,
            "showMaterialError": false,
            "materialTypeAjax": 
                "quietMillis": 300,
                "cache": false,
                "dataType": "json",
                "type": "GET",
                "url": "/lt-LT/Material/MaterialTypeNameLookup"
            
        
    ],
    "deliveryBuildings": [
        
            "clientId": "1",
            "buildingId": "1",
            "regionId": "",
            "newBuilding": false,
            "validClient": true,
            "validBuilding": true,
            "validRegion": true,
            "showClientError": false,
            "showBuildingError": false,
            "showRegionError": false,
            "propertyNames": 
                "clientName": "klientas",
                "buildingName": "ASD project, Antagynės gatvė, Kaunas, Lietuvos Respublika"
            ,
            "clientAjax": 
                "quietMillis": 300,
                "cache": false,
                "dataType": "json",
                "type": "GET",
                "url": "/lt-LT/Task/PayerLookup"
            ,
            "buildingAjax": 
                "quietMillis": 300,
                "cache": false,
                "dataType": "json",
                "type": "GET",
                "url": "/lt-LT/Object/GetClientAddressListByQuery"
            ,
            "regionAjax": 
                "quietMillis": 300,
                "cache": false,
                "dataType": "json",
                "type": "GET",
                "url": "/lt-LT/Object/RegionNameLookup"
            
        
    ],
    "hasNewBuildings": false,
    "showBuildingValidation": false,
    "showMinimumBuildingRequiredValidation": false,
    "showMaterialValidation": false,
    "validRegion": true,
    "showRegionError": false,
    "regionAjax": 
        "quietMillis": 300,
        "cache": false,
        "dataType": "json",
        "type": "GET",
        "url": "/lt-LT/Object/RegionNameLookup"
     

在表单提交失败时(如果出现问题/服务无效),它会重新填充以前的值。我们在使用$('#BuildingsJSON').val(ko.mapping.toJSON(viewModel.deliveryBuildings)) 提交表单时将 ViewModel 转换为 JSON。

在重新填充表单时,我们解析 JSON,ko.mapping.fromJSON(deliveryBuildings, mapping, viewModel.deliveryBuildings)(); mapping 现在只是一个空对象(尝试“忽略”但没有运气)。

我们使用 select2 字段从列表中选择建筑物的地址(使用 ajax)。事情是,fromJSON 将几乎每个 json 属性填充为可观察的,我不需要。在 select2 打开时,我们得到一个异常:

未捕获的类型错误:对象函数 observable() if (arguments.length > 0) // 写

        // Ignore writes if the value hasn't changed
        if (!observable['equalityComparer'] || !observable['equalityComparer'](_latestValue, arguments[0])) 
            observable.valueWillMutate();
            _latestValue = arguments[0];
            if (DEBUG) observable._latestValue = _latestValue;
            observable.valueHasMutated();
        
        return this; // Permits chained assignments
    
    else 
        // Read
        ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read"

操作 返回_最新值; 没有方法“toUpperCase”

我已经在 ajax 调用的 type 属性上调试了它的中断位置。我认为我们需要将 ajax 属性排除在转换为 observable 之外。

那么,问题是:如何将特定对象的特定属性转换为observable()?使用映射插件是否足够,是否需要额外的插件或者甚至是不可能的?

【问题讨论】:

【参考方案1】:

您是否考虑过在映射绑定中使用 copy 关键字?这只是将值复制到 js 属性中,而不是使其成为可观察的。

来自documentation:

var mapping = 
    'copy': ["propertyToCopy"]

ko.mapping.fromJS(data, mapping, viewModel);

【讨论】:

谢谢,我会试试的。而且 - 这是否可以“复制”整个对象? 好吧,它仍然将属性转换为可观察的。 你能告诉我你用过的代码吗,因为我用过 Copy 并且效果很好。 另外,如果你想复制整个对象,那你为什么要首先映射它呢? 感谢您建议使用 copy。它终于按预期工作了。至于为什么我们映射它 - 不知道。我自己是淘汰赛的新手,可能会有一些愚蠢的错误。

以上是关于Knockout.js 映射忽略的主要内容,如果未能解决你的问题,请参考以下文章

Knockout JS映射插件没有初始数据/空表单

Knockout js绑定可空对象的属性

在 knockout.js 中更改 observable 但不通知订阅者

单选按钮的 knockout.js 布尔数据绑定问题

如何将 knockout.js 与 ASP.NET MVC ViewModels 一起使用?

knockout.js入门