使用Knockout-es5显示模块模式

时间:2013-06-01 01:20:01

标签: knockout.js knockout-es5-plugin

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

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

JS Fiddle

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);
});

3 个答案:

答案 0 :(得分:2)

它没有用,因为你直接从github链接了JS。查看有效的更新小提琴:http://jsfiddle.net/tkirda/Wznkm/1/

之所以不起作用,是因为Github表示内容类型是“text / plain”而不是“application / x-javascript”。

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

因此浏览器不会执行此代码。我猜他们这样做是为了让人们停止从GitHub链接文件。

更新:在您的情况下,更改了lastName,添加console.log,您将看到它的新值。

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

但是它没有被模型使用,因为当你将它们分配给retObj时,你只传递了值而不是引用。因为string是值类型。使用函数时,它们是引用类型。所以你刚刚更新了局部变量,但你的模型没有绑定到那个变量。

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

我希望这是有道理的。

答案 1 :(得分:1)

我不确定你的问题是什么,但是对于你想要使用的模式不行。

我喜欢knockout-es5的想法,但它暴露的当前API有一些问题,如果你偏离他们的模式,这些问题确实会给你带来麻烦。

另一个问题是,如果您将this.property传递给其他视图模型,其目标是其他视图模型能够订阅observable,或者更新observable,那么它显然不起作用。你只需要传递当前值。在这种情况下,您必须记住获得物业的实际可观察​​性。使用古老的淘汰赛,你知道当你进入该物业时,你正在通过观察者。

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

答案 2 :(得分:1)

尽管我不喜欢使用构造函数和破坏的“this”关键字,但揭示模块模式几乎与ES5 ko插件完全不兼容(你可以让它在一个非常复杂的工作中运行脆弱的方式,只在简单的场景中)

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

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