Knockoutjs映射和非结构化数据

时间:2014-11-30 12:07:14

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

如何使用knockoutjs映射插件使用非结构化数据? 例如source json:

[
    {
        "id": 1,
        "name": "Store #1",
        "address": "City #1"
    },
    {
        "id": 2,
        "name": "Store #2"
    }
]

没有地址的商店#2。 我的模板:

<ul data-bind='foreach: data'>
    <li data-bind='with: id'>
        <a href data-bind='text: name, click: function () { $parent.view($data, $index()) }'>           
        </a>
        <span data-bind='text: address'></span> 
   </li>
</ul>

我的viewModel

Module.store = function () {

    var self = this;

    self.data = ko.mapping.fromJS([]);
    self.init = function () {
        $.getJSON('json/stores.json', function (stores) {
            ko.mapping.fromJS(stores, self.data);
        });
    };
};

如果我运行此代码,我会收到错误:

  

未捕获的ReferenceError:无法处理绑定&#34; text:function   (){return address}&#34;消息:未定义地址

对于商店#2

如何为Store#2地址属性设置null或空字符串?

2 个答案:

答案 0 :(得分:2)

如果您的视图显示地址,那么您的viewmodel必须包含该属性。

为各个商店制作一个视图模型:

Module.Store = function (data) {
    this.id = null;
    this.name = null;
    this.address = null;

    ko.mapping.fromJS(data, {}, this);
}

以及商店列表中的使用映射定义(请参阅documentation):

Module.StoreList = function () {
    var self = this,
        mappingDefinition = {
            create: function (options) {
                return new Module.Store(options.data);
            }
        };

    self.stores = ko.observableArray();

    self.viewStore = function (store) {
        // ...
    };
    self.init = function () {
        $.getJSON('json/stores.json', function (stores) {
            ko.mapping.fromJS(stores, mappingDefinition, self.stores);
        });
    };
};

修改后的视图(作为一般规则,尽量避免在视图定义中使用内联函数):

<ul data-bind='foreach: stores'>
    <li>
        <a href data-bind='text: name, click: $parent.viewStore'></a>
        <span data-bind='text: address'></span> 
    </li>
</ul>

答案 1 :(得分:1)

在我看来knockout-mapping-plugin开箱即用的功能并不存在。可能你应该考虑为这个问题尝试另一种解决方法,我至少可以看到两个:

1)从服务器返回带有null的json

2)有条不紊地显示该范围:

<ul data-bind='foreach: data'>
    <li data-bind='with: id'>
        <a href data-bind='text: name, click: function () { $parent.view($data, $index()) }'>           
        </a>
        <!-- ko if: address -->
        <span data-bind='text: address'></span> 
        <!-- /ko -->
   </li>
</ul>