淘汰赛 - 将值写入 ko.computed

Posted

技术标签:

【中文标题】淘汰赛 - 将值写入 ko.computed【英文标题】:Knockout - write a value to a ko.computed 【发布时间】:2014-07-26 13:44:51 【问题描述】:

我在 Knockout 中构建了一个非常注重数据/数字的应用。我目前收到错误:

未捕获的错误:无法将值写入 ko.computed,除非您 指定一个“写”选项。如果您想读取当前值,请不要 传递任何参数。

当我的自定义 bindingHandler(将数字格式化为“大”形式,即 123,345,678,987)尝试写回显示计算函数值的原始输入时,就会发生这种情况。

输入元素中显示的值:

self.value = ko.computed(function()
    return self.chosenAge().population; // 'fetched' from an array.
);

绑定处理程序:

ko.bindingHandlers.largeNumber = 
    init: function(element, valueAccessor) 
        numberInit(element);
        var value = valueAccessor();
        var interceptor = ko.computed(
            read: function() 
                // inject number formatting
                return numeral(ko.unwrap(value)).format('0,0');
            ,
            write: function(newValue) 
                // remove formatting when writing a new value
                value(numeral().unformat(newValue));
            
        );
        // display new value in target element
        if(element.tagName.toLowerCase() == 'input' ) 
            ko.applyBindingsToNode(element, 
                value: interceptor
            );
        
        else 
            ko.applyBindingsToNode(element, 
                text: interceptor
            ); 
        
    
;

【问题讨论】:

你真的想回信给你的value 计算吗?或者你想更新population 基本上,您可以告诉输入字段中显示的值是从 selectedAge 数组中获取的。我正在尝试获取它,因此如果您单击该输入元素,您可以使用largeNumber 格式输入您自己的自定义群体 【参考方案1】:

您需要在您的 ko.computed 函数中指定一个“写入”选项。请参阅documentation on computed observables。您的绑定处理程序与您的值未能更新无关。您的计算结果应如下所示:

self.value = ko.computed(
    read: function () 
        return self.chosenAge().population; // 'fetched' from an array.
    ,
    write: function (value) 
        //update your self.chosenAge().population value here
    ,
    owner: self
);

希望这会有所帮助。

【讨论】:

是的,我最初尝试过这个,我遇到的问题是把它写回去?不知道该怎么做 如果没有关于您的 chosenAge 对象的更多信息,我真的无法给您一个好的答案,您能否更新您的帖子并提供更多信息? 我认为你的代码不正确,ko.computed 里面应该是一个对象,而不是一个函数。链接也过时了,新链接是knockoutjs.com/documentation/computed-writable.html 这甚至不是正确的javascript【参考方案2】:

就我个人而言,我会在extender 中捕获您的格式实现。

定义一个扩展,使用computed 格式化程序包装可观察的数据:

ko.extenders.largeNumber = function (target, option) 

  var formatter = ko.computed( 
    read: function()
    var formatted = target().toString().replace(/\B(?=(\d3)+(?!\d))/g, ",");
    return formatted;
  ,
    write: function(nv)
        var numeric = nv.replace(/,/g,""); 
        target(numeric);

        console.log("View model now contains " + target())
  
 )
 return formatter;
;

然后创建一个使用扩展的可观察对象:(我已经将它包装在构造函数中)

function createExtendedObs(initialValue)
    return ko.observable(initialValue).extend(
    largeNumber: 
        viewModel: self
    
 );

此外,我会让我的 observable 成为数据对象中的 population 属性,它代表 chosenAge


  name: "Bronze",
  population: createExtendedObs(10000)

这不是必需的。 如果您希望将总体存储在另一个 observable 中,我将扩展器设置为通过 options 参数访问 viewModel。因此,您将以这种方式访问​​另一个可观察对象。如果要计算“其他”可观察对象,那么您需要指定 write 函数(如另一个答案中所述),这是您遇到的问题的根源。另一种选择是将subscribe 设置为chosenAge 并设置从订阅中可观察到的“其他”人口。

直接使用 data 属性,我可以按如下方式绑定到它,

<div data-bind='with: chosenAge'>  
  <input data-bind='value: population'></input>
</div>

查看my fiddle 了解完整设置。


编辑

刚刚查看了一条关于希望输入“带有”格式的值的评论。每次计算接收到一个新值时,该字段将被格式化。默认情况下,这将是焦点丢失。如果要在提供输入时对其进行修改,则需要提供 valueUpdate 绑定参数。 由于该字段是动态操作的,这将导致插入符号定位问题。您需要相应地管理插入符号的位置。

<input data-bind='value: population, valueUpdate: "afterkeydown"'></input>

【讨论】:

以上是关于淘汰赛 - 将值写入 ko.computed的主要内容,如果未能解决你的问题,请参考以下文章

淘汰赛可观察数组

将值写入远程系统的注册表[重复]

使用 open62541 将值写入 PLC 标签

如何使用 SwiftUI 将值数组写入 Firestore

使用Nodejs异步将值的总和写入另一个文件

PDO Insert 将值 1 写入具有绑定参数的所有字段