7

我正在尝试制作一个演示以使用knockout-es5 插件来简化使用显示模块模式的模型。ViewModel1 是原始的 Knockout 模型,它工作正常。ViewModel2 是尝试使用 knockout-es5 插件。遇到一些事情

  • 计算的属性不起作用,因为没有跟踪局部变量(例如 fullName1)。我可以使用 ko.defineProperty,但首先它与其他属性分开,其次必须使用 this.propertyName。
  • 由于同样的原因(例如 doSomething),成员函数所做的更改可能没有反映出来。再次使用 this.propertyName 有效,但违反了 RM 模式。

JS小提琴

var NS = NS || {};

$(function () {

    NS.ViewModel1 = function (first, last) {
        var
            firstName = ko.observable(first),
            lastName = ko.observable(last),
            fullName = ko.computed(function () {
                return firstName() + " " + lastName();
            }),
            doSomething = function (n) {
                lastName(lastName() + " " + n);
            }
        ;

        return {
            firstName: firstName,
            lastName: lastName,
            fullName: fullName,
            doSomething: doSomething
        };
    };

    NS.ViewModel2 = function (first, last) {
        var
            firstName = first,
            lastName = last,
            fullName1 = ko.computed(function () {
                // Changed values are not reflected
                return firstName + " " + lastName;
            }),
            fullName2 = ko.computed(function () {
                // Should not work
                return this.firstName + " " + this.lastName;
            }),
            doSomething = function (n) {
                // Doesn't work
                lastName += " " + n;
                // Works
                // this.lastName += " " + n;
            }
        ;

        var retObj = {
            firstName: firstName,
            lastName: lastName,
            fullName1: fullName1,
            fullName2: fullName2,
            doSomething: doSomething
        };

        ko.track(retObj);
        ko.defineProperty(retObj, 'fullName3', function () {
            // Changed values are not reflected
            return firstName + " " + lastName;
        });
        ko.defineProperty(retObj, 'fullName4', function () {
            // Works
            return this.firstName + " " + this.lastName;
        });

        return retObj;
    };

    var vm1 = new NS.ViewModel1("John", "Doe");
    ko.applyBindings(vm1, document.getElementById("observableSection"));

    var vm2 = new NS.ViewModel2("Jane", "Doe");
    ko.applyBindings(vm2, document.getElementById("withoutObservableSection"));

    setTimeout(function () {
        vm1.firstName("John 1");
        vm2.firstName = "Jane 1";
    }, 2000);

    setTimeout(function () {
        vm1.doSomething(2);
        vm2.doSomething(2);
    }, 4000);
});
4

3 回答 3

3

It did not work because you linked JS directly from github. See updated fiddle that works: http://jsfiddle.net/tkirda/Wznkm/1/

The reason for that not working, is because Github indicates that content type is "text/plain" and not "application/x-javascript".

Content-Type:text/plain; charset=utf-8
Access-Control-Allow-Origin:https://render.github.com

Therefore browsers do not execute this code. I guess they did it so that people stop hotlinking files from GitHub.

UPDATE: In your case lastName is changed, add console.log and you will see it's new value.

        doSomething = function (n) {
            // Doesn't work
            lastName += " " + n;
            console.log(lastName);
            // Works
            // this.lastName += " " + n;
        }

However it is not used by model because when you did assign them to retObj, you passed only values and not reference. Because string is value type. When you work with functions, they are of reference type. So you just updated local variable, but your model is not bound to that variable.

var retObj = {
            firstName: firstName,
            lastName: lastName,
            fullName1: fullName1,
            fullName2: fullName2,
            doSomething: doSomething
        };                                 

I hope that makes sense.

于 2013-06-01T02:53:38.713 回答
1

尽管我讨厌使用构造函数和损坏的“this”关键字,但揭示模块模式几乎与 ES5 ko 插件完全不兼容(您可以使其以非常复杂和脆弱的方式工作,并且只能在简单的场景中工作)

可跟踪的属性需要一个主机对象(因此与您的私有变量不同)并且不能被复制(因为您随后会丢失新生成的 getter)

所以选择两个邪恶中较小的一个:p(对我来说这是 ES5 语法)

于 2013-08-28T14:54:57.337 回答
1

我不确定您的问题是什么,但是是的,它不适用于您尝试使用的模式。

我喜欢 knout-es5 的想法,但是它公开的当前 API 有一些问题,如果你偏离他们的模式,真的会给你带来麻烦。

另一个问题是,如果您传递this.property给其他视图模型,目标是让其他视图模型能够订阅可观察对象或更新可观察对象,那么它显然不起作用。您将只是传递当前值。在这种情况下,您必须记住要为您的财产获取实际的 observable。使用旧的淘汰赛,您知道当您访问该属性时您正在传递可观察对象本身。

该项目还很年轻,因此希望这些 API 问题能够得到解决。但是现在,它需要开发人员记住太多事情才能做到正确。

于 2013-06-02T00:08:07.200 回答