【问题标题】:Knockout use function with mapping plugin and data binding具有映射插件和数据绑定的淘汰赛使用功能
【发布时间】:2013-08-08 07:39:43
【问题描述】:

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

这是我的视图模型和映射:

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>

也试过了:

  • &lt;td data-bind="text: FromUnixTs(date_time)"&gt;&lt;/td&gt;
  • &lt;td data-bind="text: $root.FromUnixTs(date_time())"&gt;&lt;/td&gt;
  • &lt;td data-bind="text: $root.FromUnixTs(date_time)"&gt;&lt;/td&gt;
  • &lt;td data-bind="text: date_time"&gt;&lt;/td&gt; 有效,但不像日期时间那样格式化

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

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

【问题讨论】:

    标签: knockout.js knockout-mapping-plugin


    【解决方案1】:

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

    1. 不是什么大问题,但如果您可以将数据构造成顶层不是数组本身,而是具有该数组的对象,例如{ items: [/* original data here*/] }.

    2. 对于 MVVM 模式,最好不要将逻辑放在您的视图中,text: FromUnixTs(date_time()) 与此相邻。相反,将所有这些逻辑放在您的视图模型上,并且只需一个 text: UnixTx 绑定。这也可以解决您围绕prototype 内容的问题中的问题代码。

    3. 如果您想增强使用映射插件创建的视图模型,可以通过创建映射选项来实现,以便在创建时调整模型。

    4. 1234563 )。此外,您在一个问题中提出了许多问题,从而产生了一个非常大的问题(几乎是一个审查请求),因此 SO 用户往往会回避。

    如果我将所有这些放在一起(至少 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

    【讨论】:

    • 谢谢,关于 nr4。我添加了 jQuery 部分,以防万一它与全局变量有关而无法访问它或其他东西。我以前从未在 ajax 的成功功能中创建过视图模型。未封闭的 html 只是试图保持它的可读性。但我绝对可以使用这个答案。顺便说一句,Anders 的第一个选项对我有用吗?
    • 关于第一点:我无法更改从服务器接收到的数据。所以我不能将它包装在一个对象中。但我猜 KO 映射插件采用这个 var 映射并处理那部分。但不知何故,我得到了一个items is not defined
    • 我为无法从服务器更改结果的情况添加了脚注。
    • 如果您仍然遇到问题,我建议您将其归结为smallest possible piece of code 并就该问题提出一个新问题just。这可能是从 SO 用户获得良好响应的最简单方法。祝你好运!
    【解决方案2】:

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

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

    【讨论】:

    • 您好 Anders,感谢您的回复,但我已经测试了您的第一种方法。它没有用,为什么这是一种不好的做法?
    • 即使使用viewModel.FromUnixTs = function () {&lt;td data-bind="text: FromUnixTs()"&gt;&lt;/td&gt; 我也得到FromUnixTs is not defined
    猜你喜欢
    • 2014-03-26
    • 2013-05-27
    • 2014-03-20
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 2012-09-05
    • 1970-01-01
    相关资源
    最近更新 更多