如何使用KnockoutJS,SammyJS和pagerJS组织SPA

时间:2013-02-22 10:34:59

标签: javascript knockout.js single-page-application sammy.js pagerjs

我刚开始使用KnockoutJS,我正在使用它与PagerJS,SammyJS和BootStrap组合构建单页应用程序,我现在有点迷失。

令我吃惊的是,我应该如何组织视图模型并以简单且可重用的方式组合路由和页面?现在感觉就像是一堆松散的碎片,几乎不合适。我在SO上检查了一些答案,但我仍然没有掌握如何组织应用程序。

目前我在页面上有一个视图模型,作为概念验证,它只是为用户处理个人信息和即将发生的事件的显示。但是,现在我必须合并其他类型的信息,并且似乎没有一个视图模型,而是多个视图模型,因为用户需要能够管理他/她的事件,联系人和任务以及列出其他用户,事件和任务,等等。还有更多的事情要发生。

几乎所有用户要选择/选择的选项都在数据库中定义。例如,用户任务和解决这些任务的相应操作是在数据库中预定义的。

大多数示例都倾向于将SammyJS路由放在viewmodel中,但是当在页面上有多个viewmodel时,我想将SammyJS从单个viewmodel移动到它自己,即有一个地方来编辑路由。

我的想法是使用PagerJS轻松地在不同视图之间切换,但它需要在SammyJS中设置的路径与用于PagerJS的数据绑定路径之间进行同步。例如,当选择#!/ user时,Sammy中的路由处理请求并获取要显示的数据,PagerJS显示用户页面。对我来说感觉有点脆弱,但这可能是它应该如何运作。

1 个答案:

答案 0 :(得分:2)

事先要注意一些事项:

我正在使用RequireJS将我的应用程序划分为模块 - 这不一定是必需的(没有双关语) - 您可以将所有内容转储到一个Javascript文件中并让它工作,我只是找到它更容易组织和使用。 This question显示了我的项目是如何布局的。

我也没有使用SammyJS进行路由,而是Crossroads和Hasher。这些概念应该有些相同。

以下示例可能与您正在做的事情不完全匹配,但希望它能让您了解我正在使用的方法。

我的main.js包含所有路由信息,并且在每个路由处理程序中,我使用RequireJS中的require()来引入我用于该路由的模块。每个模块都包含Knockout ViewModel和几个方法,可以为ViewModel加载数据,在某些上下文中绑定它等等。

main.js这是我如何处理显示#/person/id路线的路线:

crossroads.addRoute("person/{id}", function(id){
    require(["person"], function(person) {
        var model = person.load(id);
        person.view($('#content'), model);
    });
});

person.js的重要部分:

define(['jquery', 'knockout', ...], function($, ko, ...) {
    var person = {};
    person.Model = function Model(id) {
        this.id = ko.observable(id);
        this.name = ko.observable();
        // more properties and methods removed...
    };

    person.load = function(id) {
        var model = new person.Model(id);
        var request = $.ajax({
            // ajax config properties removed...
            'success' : function(resp) {
                model.name (resp.name);
                // more property setting removed...
            }
        });
        return model;
    };

    person.view = function(element, model) {
        // Using require text plugin to load templates...
        require(['text!templates/person/view.tmpl.html'], function(ViewTemplate) {
            element.empty();
            element.html(ViewTemplate).ready(function() {
                ko.applyBindings(model, element.get(0));
                // any further setup needed below...
            });
        });
    };
    return person;
});