Knockout使用函数与映射插件和数据绑定

时间:2013-08-08 07:39:43

标签: knockout.js knockout-mapping-plugin

我的问题与Knockout.js - javascript function on data-bind几乎完全相同 但我使用映射插件。

这是我的viewmodel和mapping:

var viewModel = ko.mapping.fromJS(data);
viewModel.FromUnixTs = function (uts) {
    var date = new Date(uts * 1000);
    var hours = date.getHours();
    var minutes = date.getMinutes();
    var seconds = date.getSeconds();
    return hours + ':' + minutes + ':' + seconds;
};
ko.applyBindings(viewModel);

这是我的html绑定:

<tbody data-bind="foreach: $root">
    <tr class="gv">
        <td data-bind="text: id"></td>
        <td data-bind="text: number"></td>
        <td data-bind="text: FromUnixTs(date_time())"></td>
    </tr>
</tbody>

也尝试过:

  • <td data-bind="text: FromUnixTs(date_time)"></td>
  • <td data-bind="text: $root.FromUnixTs(date_time())"></td>
  • <td data-bind="text: $root.FromUnixTs(date_time)"></td>
  • <td data-bind="text: date_time"></td>有效,但格式不像日期时间

  • viewModel.prototype.FromUnixTs = function (uts) {

我一直遇到的错误是:FromUnixTs is not defined或未找到。除了一个解决方案,我还想为我的错误提供更多的背景信息。我做错了什么以及为什么等等。

2 个答案:

答案 0 :(得分:1)

你有几个问题。这是我的2 cts。

  1. 不是一个大问题,但是如果您能够以顶级不是数组本身的方式构建数据,而是使用该数组的对象(例如, { items: [/* original data here*/] }

  2. 使用MVVM模式时,最好不要在视图中放置逻辑,text: FromUnixTs(date_time())与之相邻。相反,将所有逻辑放在视图模型上,只需要text: UnixTx绑定。这也适用于围绕prototype内容的问题中的有问题的代码。

  3. 如果要扩充使用映射插件创建的视图模型,可以通过创建允许您在创建时调整模型的映射选项来实现。

  4. 最后,一个阻止他人帮助你的问题:你的问题包含不相关的代码(jQuery ajax的东西)使得理解事情变得更加困难,而且这些例子是不完整的无效片段(未封闭的标签等)。此外,你在一个问题中提出了很多问题,产生了一个非常大的问题(几乎是审查请求),SO用户往往会回避。

  5. 如果我将所有这些放在一起(至少1-3),那么我建议采用不同的方法,如下所示。将您的视图更新为:

    <table>
        <tbody data-bind="foreach: items">
            <tr class="gv">
                <td data-bind="text: id"></td>
                <td data-bind="text: number"></td>
                <td data-bind="text: unixTs"></td>
            </tr>
        </tbody>
    </table>
    

    那里没有逻辑。

    然后,假设以下数据:

    var data = {
        items: [{id: 1, number:  42, date_time: 1375948769449},
                {id: 2, number: 106, date_time: 1375948769349}]
    };
    

    我使用映射插件构建视图模型,如下所示:

    var mapping = {
        'items': {
            create: function (item) {
                return new ItemViewModel(item.data);
            }
        }
    };
    
    var viewModel = ko.mapping.fromJS(data, mapping, {});
    

    这使用ItemViewModel构造函数,使用unixTs observable扩充映射的VM:

    var ItemViewModel = function (data) {
        var self = this;
        ko.mapping.fromJS(data, {}, self);
        this.unixTs = ko.computed(function () {
            var date = new Date(self.date_time());
            var hours = date.getHours();
            var minutes = date.getMinutes();
            var seconds = date.getSeconds();
            return hours + ':' + minutes + ':' + seconds;
        });
    };
    

    您可以在this fiddle中看到所有这些内容。希望这会有所帮助。


    如果无法从服务器更改数据结构,仍可以使用增强视图模型版本。有一些变化:

    // Data not augmented, just the raw array OP gets from the service
    var data = [{id: 1,number: 42,date_time: 1375948769449},
                {id: 2,number: 106,date_time: 1375948769349}];
    
    // Augment the data into an object to make a clearer view model:
    var viewModel = ko.mapping.fromJS({items: data}, mapping, {});
    

    请参阅this fiddle

答案 1 :(得分:0)

你不能在这样的对象实例上使用原型,直接将函数添加到参考工作

http://jsfiddle.net/DGzrR/

var vm = ko.mapping.fromJS(data);
vm.foo = function() {
    console.log("foo");
};

但不是好的做法,而是做 http://jsfiddle.net/DGzrR/1/

MyViewModel = function(data) {
    this.items = ko.mapping.fromJS(data);
}

MyViewModel.prototype = {
    foo: function() {
        console.log("foo");
        console.log(this.items().length);
    }
};