【问题标题】:How to access property on object in viewmodel from html code?如何从 html 代码访问视图模型中对象的属性?
【发布时间】:2012-12-10 11:09:18
【问题描述】:

我有一个如下视图模型:

define(
    ['jquery', 'knockout', 'knockout.mapping', 'data/data', 'models/models'],
    function ($, ko, mapping, data, models) {
        var post =  {},

            getPost = function (param) {
                $.when(data.deferredRequest('postDetail', param.id))
                 .done(function (result) {
                     mapping.fromJS(result, {}, post);

                     console.log(result.title === post.title()); // ---> this is true
                     console.log(ko.isObservable(post.title));   // ---> this is true
                 });
            };

        return {
            post   : post,
            getPost: getPost
        };
    });

我想在 html 中显示 title 属性如下:

<section id="section-post-detail" class="view" >
    <div class="page-header">
        <h3 data-bind="text: post.title"></h3>    <!-- show nothing -->
        <h3 data-bind="text: post().title"></h3>  <!-- error -->
        <h3 data-bind="text: post.title()"></h3>  <!-- error -->
    </div>
</section>

我尝试了三种显示 title 属性的方法,但都失败了。 我错过了什么吗?


编辑

我对源代码进行了如下调整。 我在 viewmodel 上添加了 title 属性并在 getPost 中对其进行了更新,然后我成功访问了 viewmodel 的 title 属性,而不是 post 模型上的 title 属性。

define(
        ['jquery', 'knockout', 'knockout.mapping', 'data/data', 'models/models'],
        function ($, ko, mapping, data, models) {
            var post =  {},
                title = ko.observable(''),     
                getPost = function (param) {
                    $.when(data.deferredRequest('postDetail', param.id))
                     .done(function (result) {
                         mapping.fromJS(result, {}, post);

                         title(post.title());                
                         console.log(result.title === post.title()); // ---> this is true
                         console.log(ko.isObservable(post.title));   // ---> this is true
                     });
                };

            return {
                post   : post,
                title  : title,
                getPost: getPost
            };
        });

<section id="section-post-detail" class="view" >
        <div class="page-header">
            <h3 data-bind="text: title"></h3>    
        </div>
    </section>

但是,如您所见, data-bind="text: title" 不是 post 上的 title 属性,而是 viewmodel 上的 title 属性。这不是我想要的。我想访问 post 对象的 title 属性。

请纠正我的做法。

【问题讨论】:

    标签: knockout.js


    【解决方案1】:

    不确定您何时应用绑定,但似乎在绑定时,您只是在绑定空对象。然后,当您的 AJAX 请求完成时,它会添加可观察对象,但由于 post 本身不可观察,因此 UI 不会更新。

    您可以考虑在请求完成后调用 applyBindings,例如:

    var vm = {
        post: ko.observable()
    };    
    
    //simulate AJAX
    setTimeout(function() {
        vm.post(ko.mapping.fromJS({ title: "hello" }));    
    }, 500);
    
    ko.applyBindings(vm);
    

    然后像这样绑定它:

    <section id="section-post-detail" class="view" >
        <div data-bind="with: post" class="page-header">
            <h3 data-bind="text: $data.title"></h3> 
        </div>
    </section>​​​​​​​​​
    

    【讨论】:

    • 感谢您的回答,尼迈耶。我不认为应用绑定的时间不是问题。我稍微编辑了问题,请参考问题。
    • RP 是正确的 - 当 ko 尝试应用绑定时(在第一个示例中),post 是一个空对象。它寻找 post.title,但 post 上没有这样的属性。然后它会尝试 post().title,但 post 不是一个方法,所以你会得到一个错误。然后它尝试 post.title(),但 post 对象上又不存在标题,所以你得到一个错误。
    【解决方案2】:

    我认为问题在于您最初将视图模型创建为空对象,如下所示:

    var post = {};
    

    然后您尝试更新视图模型,如下所示:

    mapping.fromJS(result, {}, post);
    

    但是,http://knockoutjs.com/documentation/plugins-mapping.html 的映射插件文档似乎表明您应该像这样创建视图模型:

    var viewModel = ko.mapping.fromJS(data);
    // or, in your case
    var post = ko.mapping.fromJS(result);
    

    那么,当你需要调用服务器获取更新数据时,你可以这样做:

    ko.mapping.fromJS(data, viewModel);
    // or, in your case
    ko.mapping.fromJS(result, post);
    

    我认为 RP 推动的重要一点是,在获得数据之前,您无法创建视图模型。

    【讨论】:

    • 感谢 CodeThung,我更新了 jsfiddle(jsfiddle.net/outia24/AVygn) 中的代码,正如你所提到的,我更改了代码并且在标题和内容属性方面运行良好,但是计算属性(在jsfiddle) 现在被添加到 post 对象中。
    • 我解决了,问题是我第一次启动模型对象时没有设置映射选项,谢谢
    猜你喜欢
    • 1970-01-01
    • 2019-08-14
    • 2018-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多