【问题标题】:Knockoutjs subscribe event , ko.computed execution timing issueKnockoutjs 订阅事件,ko.computed 执行时间问题
【发布时间】:2014-09-17 05:13:36
【问题描述】:

当 self.selectedQueryId 发生变化时,我想在 knockoutjs 中为 self.selectedTitleId() 设置不同的值,因此我添加了对 selectedQueryId 的订阅。 我有另一个计算变量 self.text 用其他变量格式化 self.selectedTitleId。

我的问题是,当我从 UI 更改 selectedQueryId 值时,首先调用计算函数,然后调用订阅。因此,我尝试显示的文本始终包含先前的选择值。

我想保持 self.text 计算函数的执行,直到 selectedTitleId.subscribe 函数完成,以便 self.selectedTitleId 具有当前值。

有人可以帮助我吗?感谢您的宝贵时间!

以下是用于将 selectedTitleId 值与 UI 绑定的 html 组件。后端 js 始终将“后端名称”显示为值,即使我尝试使用 self.selectedTitleId("newValue") 设置不同的值。 html:

      var sformat = (function() {
       var pattern = /\{\{|\}\}|\{(\d+)\}/g;
         return function () {
         var parameters = arguments;
         if(parameters[0]) {
           console.log(parameters[0])
           return parameters[0].replace(pattern, function (match, group) {
             var value;
              if (match === "{{")
                return "{";
              if (match === "}}")
                return "}";
             value = parameters[parseInt(group, 10) + 1];
             return value ? value.toString() : "";
            });
         }
       };
     });

       function test() {
         return sformat.apply(this, arguments);
       }

       self.selectedTitleId = ko.observable('');

       self.text = ko.computed(function () {
        console.log("inside text function")

        if (self.selectedTitleId && self.selectedQueryId()) {
          console.log(self.selectedTitleId)
          self.displayField = test(self.selectedTitleId, self.selectedQueryId(),self.queryValue());
        }else if(self.selectedTitleId && self.selectedQueryId() && self.queryGreaterValue() &&   self.queryLesserValue()){
          self.displayField = test(self.selectedTitleId, self.selectedQueryId(),self.queryValue(),self.queryGreaterValue(),self.queryLesserValue());
        }
     return self.displayField;
    });

    self.selectedQueryId.subscribe(function (newValue) {

        $.getJSON("json/queries.json", function (allData) {
            var mappedData = $.map(allData, function (item) {
                if(item.DisplayName == "Price"){
                    if(newValue == "range") {
                        self.selectedTitleId(item.RangeBackEndFieldName);
                        console.log("range");
                        console.log(item.RangeBackEndFieldName); //Prints new string
                        console.log(self.selectedTitleId()); //Print old value- 
                    }else if(newValue == "$gt:" || newValue == "$lt:"){
                        self.selectedTitleId(item.BackendFieldName);
                        });
                    }
                }
            });
        });
});

【问题讨论】:

    标签: javascript knockout.js


    【解决方案1】:

    除非您没有告诉我们其他事情,否则selectedTitleId 成为ko.computed 是没有意义的。只需使用常规的 observable:

    self.selectedTitleId = ko.observable();
    
    self.selectedQueryId.subscribe(function (newValue) {
    
        $.getJSON("json/queries.json", function (allData) {
            var mappedData = $.map(allData, function (item) {
                if(item.DisplayName == "Price"){
                    if(newValue == "range") {
                        self.selectedTitleId(item.RangeBackEndFieldName);
                        });
                    }else if(newValue == "$gt:" || newValue == "$lt:"){
                        self.selectedTitleId(item.BackendFieldName);
                        });
                    }
                }
            });
        });
    });
    

    现在当selectedTitleId 在您的回调中更改时,它应该会触发text 重新评估。

    你原来的问题不在于它首先更新text,而是当你更改selectedTitleId时它没有重新评估。见这里:

    if (self.selectedTitleId() && self.selectedQueryId()) {
    

    这意味着您的computed 属性同时依赖于selectedTitleIdselectedQueryId,更新其中任何一个都会导致函数再次运行。但是在您的原始代码中,您将 self.selectedTitleId 完全替换为一个全新的函数,但您的 computed 仍然依赖于旧函数(未更改)。

    【讨论】:

    • 感谢您的解释。是的你是对的。我试图让它成为一个函数来让 sformat 函数工作。 sformat 函数用于模仿 java 中的 String.format 函数,它用传递的参数替换给定字符串中的 {0} {1}...。
    • 我尝试通过测试方法将 self.selectedTitleId 传递给这个 sformat,但我总是得到 TypeError: parameters[0].replace is not a function。当我尝试调试什么是参数 [0] 时,它给了我 d()。我想将字符串传递给测试方法。如果我将 self.selectedTitleId 设为一个函数,我能够将 self.selectedTitleId() 传递给测试方法并且格式工作正常..这是我的确切问题..为了解决这个问题,我将 selectedTitleID 更改为导致计算函数问题的函数..
    • @user3773712:你的 observable 是一个函数(从功能上讲,它几乎就是你在 computed 中所拥有的),所以要将值 inside 传递给 observable,你只需调用该函数。所以myfunction(self.selectedTitleId()) 会将值从你的 observable 传递给myfunction。所以据我所知,你在做什么,你应该能够像使用计算一样使用 observable。
    • 我刚刚编辑了我的问题。在制作 self.selectedTitleId("newValue") 行后,我尝试了一些 console.log 来查看 self.selectedTitleId 值是否已更改。但它根本没有改变。当我尝试 ko.computed 时,值发生了变化。
    • 仅用部分代码很难判断,但您对self.selectedTitleId 的定义在哪里?我还注意到您更改了 text 计算中的 if 语句。那仍然应该是self.selectedTitleId(),因为self.selectedTitleId 总是会返回一个函数(如果你这样做了,确实让它成为一个可观察的),这总是真实的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-06
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    相关资源
    最近更新 更多