如何使用用户角色构建视图和ViewModel?

时间:2014-02-19 09:48:17

标签: javascript durandal durandal-2.0

我正在开发一款需要不同视图的应用,具体取决于用户角色。最初,我设法使用包含ajax请求操作和模型的单独文件夹将我与API的交互分开,以避免在VM中重复代码。

  • app/controllers/ - 包含每个对象的GETPOSTPUTDELETE操作和模型

然后我有了应用程序其余部分的结构:

app/building/ [route:building/]
  - shell.html
  - shell.js
  - /offices (list of offices)
    - index.html
    - index.js
  - /equipment (list of equipments)
    - index.html
    - index.js

app/offices/ [route:offices/:id]
  - shell.html
  - shell.js
- /employees (list of employees)
  - index.html
  - index.js
- /details (office details)
  - index.html
  - index.js

app/employees/ [route:employees/:id]
  - shell.html
  - shell.js
  - /report (individual employee data)
    - index.html
    - index.js
  - /details (empoyee details)
    - index.html
    - index.js

这将是管理员角色。如您所见,很多shell,子shell,子路由器和路由。并且需要进行更改,因为并非所有角色都可以访问相同的路径。

首先,我尝试了viewURL方法,我在会话开始时保存角色,只使用viewUrl提供适当的视图,但后来我注意到文件太过膨胀:

  • 必须更改主路由器和子路由器,并删除较低级别用户的声明路由
  • 每个页面(admin.html,employee.html)的单独视图共享相同的视图模型,其中包含员工永远不会使用的功能

然后我提出了另一种结构。它与以前一样,除了每个角色都有自己的文件夹:

app/roles/admin/
  - building/
    - ...
  - offices/
    - ...
  - employees/
    - ...
app/roles/employee
  - building/
    - ...
  - offices/
    - ...
  - employees/
    - ...

当应用程序加载时,我只需根据角色设置根目录即可。

优点

  • 更容易单独维护
  • 除应用启动之外没有角色检查
  • 特定于角色的代码,没有任何混淆其他角色的风险

缺点

  • 更多文件
  • 作为一个群体难以维持。例如,如果我重写一个在所有角色之间共享的函数,我必须替换每个角色的代码

我觉得第二种结构更加舒适,但我想知道你们的想法。或者,如果您有更好的处理角色的方法。

1 个答案:

答案 0 :(得分:0)

有很多不同的方法可以解决这个问题(例如,我想到了自定义viewLocator.convertModuleIdToViewId方法),但我认为你所得到的是好的,前提是你不要在“每个不同角色的“view / viewModel”相同。

我唯一不喜欢的是你最终会得到“数百”名为“index.js”和“index.html”的文件,如果你使用的是R很难找到#。

为了解决“难以作为一个群体维护”问题,您可以相当轻松地将公共代码重构为“全部​​”角色,然后将其用于特定角色。如下所示:

app/roles/all/
  - building/
    - buildingCore.js
  - offices/
    - officesCore.js

然后是buildingCore.js(显然我只是在这里编写方法):

define([], function() {
    var someCommonBuildingFunction = function() {
        // whatever
    }

    return {
        doSomething: someCommonBuildingFunction
    }
});

然后在(比方说)admin/building/building.js

define([
    "roles/all/buildingCore"
],

function(buildingCore) {
    var viewModel = {
        activate: function() {
            buildingCore.doSomething()
        }
    }

    return viewModel;
});