可写的计算可观察量是否真的需要额外的内部可观察量?

时间:2017-03-29 20:23:49

标签: javascript knockout.js computed-observable

我正在尝试使用可写的计算observable,但实际上并没有得到它为什么我只是输入它就无法在observable中获取一些数据。我发现我需要额外的observable来复制write:read:的内容,这看起来很奇怪。

        self.fullName = ko.pureComputed({
            read: function () {
                return ...data from other observables to show in the observable;
            },
            write: function (value) {
                  // value is the content in the input
                  // can be sent to other observables                                       
            },
            owner: self
        });

我发现在上面的模型中,你在observable中输入的内容并不在里面。

在下面的完整示例中(包括测试输出和注释),我使用额外的observable将数据从write:复制到read:。在我的项目中至关重要的是复选框,以决定是否通过键入其中一个来获得两个相同的可观察量,或者通过键入两个可观察量来区别对待。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Writable computed observables</title>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <script src='https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js'></script>
    </head>
    <body>
        <h1>Writable computed observables</h1>
        <p>See: <a href="http://knockoutjs.com/documentation/computed-writable.html">Knockout Doc</a></p>
        <h2>Original example</h2>
        <div>
            First name: <input data-bind="textInput: firstName" />
            <span data-bind="text: firstName"></span>
        </div>
        <div>
            Last name: <input data-bind="textInput: lastName" />
            <span data-bind="text: lastName"></span>
        </div>
        <div class="heading">
            Hello, <input data-bind="textInput: fullName" />
            <span data-bind="text: fullName"></span>
        </div>
        <h2>My example</h2>
        <div>
            Name: <input data-bind="textInput: Name" />
            <span data-bind="text: Name"></span>
        </div>
         <div>
            Mirror first name? <input type="checkbox" data-bind="checked: cbMirror" />
            <span data-bind="text: cbMirror"></span>
        </div>
        <script>
            function MyViewModel() {
                var self = this;
                // example from knockout site:
                self.firstName = ko.observable('Planet');
                self.lastName = ko.observable('Earth');

                self.fullName = ko.pureComputed({
                    read: function () {
                        //return;
                        return self.firstName() + " " + self.lastName();
                    },
                    write: function (value) {
                          // value is the content in the input field, visible on form,
                          // but apparently not yet in the observable.
                          // now copy this value to first/last-name observables,
                          // that in turn copy it to the read-function,
                          // that returns it to the observable.
                        var lastSpacePos = value.lastIndexOf(" ");
                        if (lastSpacePos > 0) { // Ignore values with no space character
                            self.firstName(value.substring(0, lastSpacePos)); // Update "firstName"
                            self.lastName(value.substring(lastSpacePos + 1)); // Update "lastName"
                        }
                    },
                    owner: self
                });

                // checkbox whether or not to mirror between two fields            
                self.cbMirror = ko.observable(false);
                // this observable is to help the writable computed observable to copy input from write() to read()
                self.tmpName = ko.observable();
                // the writable computed observable that may mirror another field, depending on the checkbox
                self.Name = ko.pureComputed({
                        read: function () {
                            return self.cbMirror() ? self.firstName() : self.tmpName();
                        },
                        write: function (value) {
                            //if (self.cbMirror()){
                            //  self.firstName(value);
                            //}else{
                                self.tmpName(value);
                            //}
                        },
                        owner: self
                });
            }

            ko.applyBindings(new MyViewModel());
        </script>
    </body>
    </html>

这个问题因此:在没有额外可观察write:的情况下直接从read:self.tmpName获取一些内容真的没有更好的方法吗?

更新

根据下面的答案中获得的理解,我可以简化示例代码的write:部分,查看我注释掉的不需要的代码。

1 个答案:

答案 0 :(得分:1)

是的,如果要存储用户输入,则需要一个observable。计算出的信息不存储它只修改它的信息。这就像变量和函数之间的区别。函数不会存储它们的值,以便以后查看它只修改输入并给出输出。

可写计算的observable不存储数据。它将数据传递给后备可观察对象。写入部分的全部要点是获取值并将其存储在某处。如果添加另一个范围来查看tmpName的值,除非选中cbMirror,否则您将看到它存储了您输入的内容。