【问题标题】:Computed observable when using JSON in knockout在淘汰赛中使用 JSON 时计算的 observable
【发布时间】:2013-11-27 13:12:20
【问题描述】:

我正在寻求一些淘汰建议。这个问题我已经发帖了,但是我的理解发生了变化,所以我重新发布。

我有以下代码:

function updateViewModel() {
    if (typeof groupId == 'undefined') {
        groupId = getDefaultGroupId();
    }

    $.getJSON("api/livestatusgroup/children/" + groupId)
        .done(function (data) {
            ko.mapping.fromJS(data, liveStatusViewModel.groups);
            groupsLoaded();
        });

    $.getJSON("api/livestatusgroup/resources/" + groupId)
        .done(function(data) {
            ko.mapping.fromJS(data, liveStatusViewModel.resources);
            resourcesLoaded();
        });

    this.resourceImagePath = ko.computed(function () {
        return "../Image/" + this.resourceID();
    }, this);
}


function ViewModel() {
    var self = this;
    self.resources = ko.mapping.fromJS([]);
    self.groups = ko.mapping.fromJS([]);
}

如您所见,我正在使用 JSON 加载我的视图模型,但我在使用 resourceID() 方法时遇到了问题。我不确定如何编写将 this.resourceID() 替换为资源 ID(例如 ../Image/1)的方法。我试过使用这样的计算观察者:

    liveStatusViewModel.resources.resourceID() = ko.computed(function() {
        return this.ResID;
    }, liveStatusViewModel);

...但这没有用。谁能帮我吗?我浏览了整个互联网,包括 Stack Overflow,但没有运气。这是一个真正的绊脚石!

进一步的工作

我刚刚尝试更改将 /Image/xx 附加到图像 src 的方式,如下所示:

    function resourceImagePath(resourceId) {
        return "/Images/" + resourceId;
    }

使用以下 HTML 标记

<div class="icon" id="resourceIcon" runat="server"><img data-bind="attr: { src: resourceImagePath(ResourceId) }" alt=""/></div>

这不起作用。烦人的是,上面的resourceImagePath函数改写成这样:

    function resourceImagePath(resourceId) {
        return "/Images/1";
    }

使用硬编码的图像 ID 进行测试,绝对可以正常工作。

理想情况下,我想知道如何使 JSON 中的资源 ID 可观察。

有人有其他想法吗?

谢谢,马克

【问题讨论】:

  • 我在您之前的问题中问过,并且会再次问:您能否向我们展示完整的模型代码,包含 ResID,以及您调用updateViewModel() 的代码。顺便说一句,如果你的 resourceID() 是在 liveStatusViewModel 中声明的,为什么你希望它可以通过 updateViewModel 函数作为 this.resourceID() 访问?
  • 我没有模型的代码,它是使用 JSON 填充的。我从 $(document).ready 函数调用 updateViewModel()。

标签: c# knockout.js


【解决方案1】:

我认为您的结构不正确,因为计算函数“resourceImagePath”应该是单个资源的定义。

我知道您可能想要使用该映射插件,但根据我的经验,我发现手动映射时我有更大的灵活性。这不好玩,但你做一次然后继续。

以下是我的处理方法。我根本没有测试过。

  1. 定义您的视图模型(“资源”、“组”、“视图模型”; 包括计算变量)

  2. 在加载文档时调用 viewModel.Initialize 函数

  3. 在通过 JSON 结果(即“数据”)初始化循环时调用以收集数据和
    创建 Javascript 对象的新实例(即“资源”、“组”)

    // global variable
    var groupId;
    
    
    // define view models
    var resource = function(resourceID){
        var self = this;
    
        self.resourceID() = ko.observable(resourceID);
    
        self.resourceImagePath = ko.computed(function () {
                return "../Image/" + self.resourceID();
        }, self);
    }
    
    // define group
    var group = function(groupId){
        var self = this;
        self.groupID() = ko.observable(groupId);
    }
    
    var viewModel = function() {
            var self = this;
            self.resources = ko.observableArray([]);
            self.groups = ko.observableArray([]);
    
            self.Initialize = function(){
    
                if (typeof groupId == 'undefined') {
                        groupId = getDefaultGroupId();
                }
    
                $.getJSON("api/livestatusgroup/children/" + groupId)
                        .done(function (data) {
                                for(var i = 0, j = data.length; i< j; i++){
                                    self.groups.push(new group(data[i].groupID))                            
                                }                                                       
                                groupsLoaded();
                        });
    
                $.getJSON("api/livestatusgroup/resources/" + groupId)
                        .done(function(data) {
                                for(var i = 0, j = data.length; i< j; i++){
                                    self.resources.push(new resource(data[i].resourceID))                           
                                }                                                       
                                resourcesLoaded();
                        });     
    
            }
    
    }
    
    
    var vmContext;
    $(function () {
        vm = new viewModel();
        vm.Initialize();
    });
    

【讨论】:

    【解决方案2】:

    乍一看,我发现了几个潜在的问题。

    <img data-bind="attr: { src: resourceImagePath(ResourceId) }" />
    

    这里的问题是您在调用 resouceImagePath 函数时没有解析 observable。直接调用时只能使用不带括号的可观察对象,如

    <img data-bind="attr: { src: SourceObservable }" />
    

    所以,正确的写法应该是

    <img data-bind="attr: { src: resourceImagePath(ResourceId()) }" />
    

    另外,您计算的 ResourceID 未正确分配。

    liveStatusViewModel.resources.resourceID() = ko.computed(function() {
        return this.ResID;
    }, liveStatusViewModel);
    

    在这里,您在 resourceID 上添加括号,它尝试解析函数,同时还尝试在表达式的右侧分配一个值。这不是有效的 JavaScript。删除括号后,它应该可以工作。

    liveStatusViewModel.resources.resourceID = ko.computed(function() {
        return this.ResID;
    }, liveStatusViewModel);
    

    至于您帖子的其余部分,我不太了解您要做什么,所以这是我能给出的最佳答案。我不确定是否要将 resourceID 分配给 liveStatusViewModel.resources 上的每个资源,或者是否要添加在 liveStatusViewModel.resources 对象上计算的资源。如果您澄清,我将能够进一步回答。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-02
      • 2016-07-21
      • 2020-05-30
      • 2013-03-22
      • 1970-01-01
      • 2013-04-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多