KnockoutJS 是否为构建大型 Web 应用程序提供了合适的架构? [英] Does KnockoutJS provide suitable architecture for building large web apps?

查看:21
本文介绍了KnockoutJS 是否为构建大型 Web 应用程序提供了合适的架构?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

快速问题:

KnockoutJS 会为开发大型网络应用程序提供坚实的基础吗?我担心有一个巨大的 viewModel 会变得无法维护.

背景信息

我将构建一个主要基于客户端的网络应用程序.后端将只是一个 RESTful 端点.Web 应用程序的整个界面将构建在纯 HTML/CSS/JS 中 - 不涉及服务器端脚本.

网络应用程序本身将包含多个具有一个通用登录名的较小应用程序(有点像 Google 的网络应用程序,其中包含 Gmail、文档、日历、阅读器等).

这些网络应用中的每一个都将具有一些通用功能(例如侧边栏树视图、顶部栏菜单视图、通知系统)和一些应用独有的功能.通常我会分解我的应用程序以封装功能,例如:

var myNamespace = {常见的: {设置:{},用户:{},通知:{}},应用 1:{},应用 2:{},应用 3:{}};

现在,我真的很喜欢使用 KnockoutJS 并认为它在构建我的项目的某些元素时会很有帮助(例如通知系统,或具有自动刷新功能的高级网格视图,因为应用程序将支持协作).但我就是不知道把我的 viewModel 放到这个结构的哪里.

我只能找到有关如何使用 KnockoutJS 构建应用程序的简单示例.你真的能用它来构建比 Twitter 阅读器更高级的东西吗?有没有什么很好的例子来说明如何在 viewModel 中分解很多功能,或者分解成许多 viewModel?

建议的解决方案

虽然更理论化的问题(快速问题)在这里仍然没有答案,但我想我已经找到了一个在实践中有效的解决方案.@Simon 的回答让我深思,这就是我目前得到的:

//首先:我想分享的 Observables 的集合ld.collectionOfObservables = {通知:ko.observableArray([]),};//现在让我们定义一个视图模型.我把我所有的东西都放在里面//'ld' 命名空间以避免混乱全局对象.ld.viewModel1 = 函数(参数){//查看内部参数并绑定所有给定的参数//通常你会希望 args 是 Observables 的对象.for (var 参数中的键) {if (args.hasOwnProperty(key)) {这个[key] = args[key];}};//所以,现在我们已经有了一些可观察的//'this',如果在 'args' 中提供了任何内容.//此外,我们定义了一些模型独有的属性/可观察对象this.folders = [ '收件箱', '存档', '已发送', '垃圾邮件'];this.selectedFolder = ko.observable('收件箱');};//*** 让我们假设我创建了类似的类并将其命名为 ld.viewModel2 ***ld.viewModel2 = 函数(参数){ .... }//好的,现在继续实例化我们的视图模型!//这是有趣的部分:我们可以在这里提供 0-many observables,通过在一个对象中提供它们//这样我们就可以通过简单地将相同的 observables 提供给不同的 viewModels 来在 viewModels 之间共享 observablesvar vm1 = 新的 ld.viewModel1({通知:ld.collectionOfObservables.notifications,//我们采用集合中定义的 Observable});var vm2 = 新的 ld.viewModel2({通知:ld.collectionOfObservables.notifications,//与 vm1 共享});//当然,我们可以将整个 ld.collectionOfObservables 作为数组发送//但我想表明您可以更灵活地选择要分享的内容.//不容易用 *one* 共享 Observable 来说明 - 通知 -//但我希望你明白这一点.:)//最后,在指定范围内启动新的viewModelsko.applyBindings(vm1, document.getElementById('leftPane'));ko.applyBindings(vm2, document.getElementById('bottomPane'));

现在,如果 JS 有真正的继承,那就更好了,因为现在我觉得我所有的 viewModel 都是从这个开始的:

for (var key in args) {if (args.hasOwnProperty(key)) {这个[key] = args[key];}};

但这只是一个小小的不便.让我知道你的想法!

编辑 1:解决方案是否可以像使用 with: 绑定一样简单?请参阅1.控制流绑定"为例.

编辑 2:我觉得我上次编辑太快了.with: 绑定可能有助于您的代码结构,但 AFAIK 它不能帮助您在这些不同部分之间共享 observables.所以上面提出的解决方案仍然是可行的.

解决方案

您可以使用部分视图并在它们之间共享可观察对象.

 var some_observable = ko.observable()var Model1 = 函数(某物){this.something_1 = 东西;};var Model2 = 函数(某物){this.something_2 = 东西;};var view_1 = Model1(some_observable);var view_2 = Model2(some_observable);ko.applyBindings(view_1, document.getElementById('some-id'));ko.applyBindings(view_2, document.getElementById('some-other-id'));<div id='some-id'><input data-bind='value: something_1'/>

<div id='some-other-id'><input data-bind='value: something_2'/>

我一直在使用这种方法在图库应用程序中维护照片列表,其中一个视图呈现缩略图,另一个视图负责上传.

Quick question:

Will KnockoutJS provide a solid ground for developing a large web app? I am afraid of having one huge viewModel that will become unmaintainable.

Background info

I'll be building a web app that will be heavily client-side based. The backend will just be a RESTful endpoint. The entire interface of the web app will be built in pure HTML/CSS/JS - no server side scripting involved.

The web app itself will consist of several smaller apps with one general login (kind of like Google's web apps where you have Gmail, Docs, Calendar, Reader, etc.).

Each of those web apps will have some common functionality (such as a sidebar tree view, a top bar menu view, a notifications system), and some app-unique features. Usually I break my apps down to encapsulate functionality, something like:

var myNamespace = {
    common: {
        settings: {},
        user: {},
        notifications: {}
    },
    app1: {},
    app2: {},
    app3: {}
};

Now, I really enjoy working with KnockoutJS and figured that it will be helpful when building some elements of my project (such as the notification system, or an advanced grid view with auto-refresh as the app will support collaboration). But I just can't figure out where to put my viewModel into this structure.

I can only find trivial examples of how to build apps with KnockoutJS. Can you actually build something more advanced than a Twitter reader with it? Are there any good examples of how to break down a lot of functionality in the viewModel, or perhaps into many viewModels?

Proposed solution

While the more theoretical question (the Quick question) is still kind of unanswered here, I think I've found a solution that works in practice. @Simon 's answer gave me some food for thought, and here's what I've got so far:

// First: a collection of Observables that I want to share
ld.collectionOfObservables = {
    notifications: ko.observableArray([]),
};

// Now let's define a viewModel. I put all my stuff inside the
// 'ld' namespace to avoid cluttering the global object. 
ld.viewModel1 = function (args) {
    // Look inside args and bind all given parameters 
    // Normally you will want args to be an object of Observables. 
    for (var key in args) {
        if (args.hasOwnProperty(key)) {
            this[key] = args[key];
        }
    };
    // So, by now we already have some observables in
    // 'this', if there were any supplied in 'args'.
    // Additionally, we define some model-unique properties/observables
    this.folders = [ 'Inbox', 'Archive', 'Sent', 'Spam' ];
    this.selectedFolder = ko.observable('Inbox');
};
// *** Let's pretend I create similar class and call it ld.viewModel2 ***
ld.viewModel2 = function (args) { .... }

// OK, now go on and instantiate our viewModels!
// This is the fun part: we can provide 0-many observables here, by providing them in an object
// This way we can share observables among viewModels by simply suppling the same observables to different viewModels
var vm1 = new ld.viewModel1({ 
    notifications: ld.collectionOfObservables.notifications,  // we take an Observable that was defined in the collection
});
var vm2 = new ld.viewModel2({ 
    notifications: ld.collectionOfObservables.notifications,  // shared with vm1
});

// Of course, we could just send the entire ld.collectionOfObservables as an array 
// but I wanted to show that you can be more flexible and chose what to share.
// Not easy to illustrate with *one* shared Observable - notifications - 
// but I hope you get the point. :)

// Finally, initiate the new viewModels in a specified scope
ko.applyBindings(vm1, document.getElementById('leftPane')); 
ko.applyBindings(vm2, document.getElementById('bottomPane'));

Now, if JS had real inheritance it'd be even better cause right now I feel that all my viewModels start with this:

for (var key in args) {
    if (args.hasOwnProperty(key)) {
        this[key] = args[key];
    }
};

But that's just a minor inconvenience. Let me know what you think!

Edit 1: Could the solution be as simple as using the with: binding? See "1. Control flow bindings" for an example.

Edit 2: I think my last edit was too quick. with: binding may help with the structure of your code, but AFAIK it doesn't help you share observables between those different parts. So the proposed solution above is still the way to go.

解决方案

You can use partial views and share observables between them.

    var some_observable = ko.observable()

    var Model1 = function(something) {
        this.something_1 = something;
    };
    var Model2 = function(something) {
        this.something_2 = something;
    };

    var view_1 = Model1(some_observable);
    var view_2 = Model2(some_observable);

    ko.applyBindings(view_1, document.getElementById('some-id'));
    ko.applyBindings(view_2, document.getElementById('some-other-id'));

    <div id='some-id'>
        <input data-bind='value: something_1' />
    </div>
    <div id='some-other-id'>
        <input data-bind='value: something_2' />
    </div>

I've been using this aproach to maintain a list photos in a gallery application, where one view renders thumbnails and another view takes care of uploads.

这篇关于KnockoutJS 是否为构建大型 Web 应用程序提供了合适的架构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆