3

我正在使用基于 Durandal 的 SPA,并遵循他们拥有“视图”和“视图模型”的约定,基本功能运行良好。即使用somepage.html& somepage.js

但是,当添加更多交互式 UI 元素(例如可折叠的手风琴或信息弹出窗口)时,处理这些事件的 javascript 应该去哪里?将它放在视图模型somepage.js文件中并不“闻起来”正确 - 那是为了......视图模型

somepage.html从最佳实践的角度来看,在我的文件中包含一个脚本块会更好吗?例如

<section>
    <!- html markup and data-binding goes here>
</section>

<script type="text/javascript">
    <!-- UI-only Javascript goes here>
</script>

或者,还有更好的方法?

4

3 回答 3

3

您的纯 GUI javascript 元素应该通过 html 数据属性绑定到 UI。例如,引导手风琴将具有以下 html (此处的引导文档)

<div class="accordion" id="accordion2">
  <div class="accordion-group">
    <div class="accordion-heading">
      <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseOne">
        Collapsible Group Item #1
      </a>
    </div>
    <div id="collapseOne" class="accordion-body collapse in">
      <div class="accordion-inner">
        Anim pariatur cliche...
      </div>
    </div>
  </div>
.......

以及页面底部引用的引导 javascript 文件。

于 2013-05-16T19:31:32.083 回答
3

我也一直在为此苦苦挣扎,并且我同意将与视图相关的东西放入 viewModel 的气味中。我需要做你所说的事情的原因是附加一个委托的事件处理程序- 这不能像建议的那样使用自定义绑定或小部件来完成。

我和同事想出的最佳解决方案是viewAttached从 viewModel 传播事件,并在“视图文件”中侦听事件。

以名为“awesome”的视图为例,我们使用如下命名约定:

  • 视图模型- viewmodels/awesome.js
  • 查看-views/awesome.html
  • 查看文件-views/awesome.html.js

这是我们正在做的事情的简化版本。

viewmodels/awesome.js:

define([
    "durandal/app",
    "durandal/system",

    // require the view file; note we don't need a reference to it,
    // we just need to make sure it's loaded
    "views/myView.html"
],

function (app, sys) {
    var viewModel = {
        // whatever
    };

    viewModel.viewAttached = function(view) {
        // Create a namespace for the event
        var eventNamespace = sys.getModuleId(viewModel)
            .replace("viewmodels", "")
            .replace("/", ".");

        // This will evaluate to 'awesome.viewAttached'
        var eventName = eventNamespace + ".viewAttached";

        // Trigger the event and pass the viewModel and the view
        app.trigger(eventName, viewModel, view);
    };

    return viewModel;
});

意见/awesome.html.js:

define([
    "durandal/app"
],

function (app) {
    var module = {
        viewAttached: function(viewModel, view) {
            // do your thing! make sure any selectors you use use the view as the parent selector,
            // because you're not guaranteed that your view is in the DOM (only that it's attached
            // to its parent).
            var $submit = $("#submit", view);
        }
    };

    // wire-up
    app.on("awesome.viewAttached", module.viewAttached);

    // export
    return module;
});

希望有帮助。

于 2013-05-17T03:43:37.730 回答
1

viewAttached 是一个相当危险的小东西……它很想把所有的 JS 代码放在那里……但它并不理想。我发现的一个小怪癖是在嵌套视图模型中

家长 第 1 步(孩子 1) 第 2 步(孩子 2)

父母开关(child1 <--> child2)

如果父级操作子视图(从子级 1 交换到子级 2)viewAttached 将不会在子级上正确触发(此时 DOM 尚不可用)并且由于父级已经附加它不会运行 viewAttached在父母身上!

所以突然你发现你所有的 JS 模块都将停止工作,然后你必须为需要由外部 JS 修改的元素做 ko customBindings。

于 2013-05-26T07:32:16.810 回答