0

我是 Backbone.js 的新手,在为模型视图关系找出合适的架构时遇到了麻烦。

我有一个视图,其中包含一个输入框和一个模型,该模型应该获取该输入框的内容并将其发送到服务器。

我的问题是我并不总是有一个谨慎的 DOM 事件来触发对视图更新模型数据的请求,例如input.change. 有时代码本身需要要求模型向服务器发送更新。

到目前为止,我已经想到了三个解决这个问题的方法,但我不确定它们是否有用:

  • 在输入元素的keypress事件上更新模型

  • 使用模型初始化视图后,让视图更新/向模型添加一个名为“ get_input_value()”的函数,该函数返回输入框的值

  • 每当应用程序需要请求模型更新服务器时,首先调用视图中的一个函数,将用户在视图中键入的所有信息更新到模型中。

请记住,这是一个简化的示例。视图还包含子视图,所有子视图都包含许多用户可以操作的元素,模型需要使用所有这些信息进行更新,以便它可以更新服务器。

任何帮助和意见表示赞赏!非常感谢!

编辑 :::

根据 machineghost 的回复,我现在看到我没有正确表达这个问题:

有一个 DOM 事件,但问题是它不一定来自使用模型的视图内部。它可能源自路由器或其他视图,并由全局事件处理程序触发。此外,没有 1:1 的视图模型关系。该模型由以不同方式表达模型的多个视图使用。所以在这种情况下,更新服务器的命令似乎不应该通过视图,而是通过模型本身。如果是这种情况,模型必须能够说“用我的观点同步我!”。

但我不知道如何在不违反规则的情况下做到这一点,从而在架构上产生其他问题......

4

1 回答 1

4

好的,这是一个主观的问题,所以如果这看起来像是我喷了两分钱,请原谅我。在我回答你的问题之前,我不得不承认我有点怀疑你:

并不总是有谨慎的 DOM 事件

因为几乎用户可以做的任何事情都会触发您可以观察的事件。例如,如果您想等到用户更改文本输入,则有change,而且(如您所述)各种key*事件,还有blur(通常用于此类事情)。在 3(+) 之间,您应该始终能够适当地响应用户的操作。只有(比如说)您必须每 3 秒保存一次文本输入的内容,它才会真正独立于 DOM 事件。

所以,在不知道你的细节的情况下,我只需要指出那里有什么东西闻起来有腥味。但是无论如何,至于您的实际问题,这是我对您的想法的看法:

在输入元素的按键事件上更新模型

这当然可以,但一定要使用视图来进行实际的事件处理/模型设置;在模型中连接 onKeyPress 处理程序将是一个坏主意

总的来说,这种方法看起来很标准,并且符合 Backbone 范式。

使用模型初始化视图后,让视图更新/向模型添加一个名为“get_input_value()”的函数,该函数返回输入框的值

我不太明白这对你的问题有什么帮助,而且它似乎把问题放在了错误的地方:模型应该(理想情况下)与 DOM 无关。

每当应用程序需要请求模型更新服务器时,首先调用视图中的一个函数,将用户在视图中键入的所有信息更新到模型中。

保存是每 5 分钟发生一次吗?如果不是,那么它可能是为了响应用户的操作而发生的,您应该使用事件处理程序来响应。

但是,如果您确实需要使同步独立于用户操作,我建议您使用自定义事件来管理事情。换句话说,在模型的同步方法中放置类似this.trigger('preSync'). 然后,使用该模型的每个视图都可以绑定某种updateMyModelValue方法,即。this.model.on('preSync', this.updateMyModelValue, this);.

这样,您的模型代码根本不会直接与 DOM 交互;相反,它只是担心它应该担心的东西(数据),并且视图会注意何时需要从 DOM 更新该数据。

希望有帮助。

*编辑(回应您对问题的编辑) *

如果是这种情况,模型必须能够说“用我的观点同步我!”。

模型的一般 Backbone 方式...嗯,它的视图几乎所有内容都是通过事件。

(从技术上讲,您可以在模型本身中维护模型视图的列表,然后遍历该列表以告诉视图执行操作。Backbone 甚至没有足够的意见让您这样做。但是,从可维护性的角度来看,对我来说似乎是一种可怕的方法。)

我的“预同步”事件示例(上图)演示了如何使用这种技术;如果有任何不清楚,请回复评论。

同样,如果您有以下问题:

  1. 视图 A 捕获事件
  2. 视图 B 需要做一些事情来响应那个事件

你基本上有两个选择:

1)您可以将两个视图紧密耦合。假设有一个创建行视图的表视图,但需要响应这些行中发生的事件。您可以在创建表时将表本身作为选项传递给行 ( new Row({table:this})),然后当这些行需要告诉他们的表“发生事件”时,他们可以这样做this.options.table.informThatAnEventHappened()。如果两个视图本质上是相关的,那么这是一个很好的方法,比如一个表和它的行。如果没有,更好的方法是:

2)您可以使用事件在视图之间进行通信。假设您在页面顶部有一个标题 div,每当“标题”文本输入发生变化时都需要更新它......但是该文本输入在页面下方并且在概念上与页面的标题(除了设置它)。这两个元素(及其视图)之间的共同点是数据,即标题本身的文本。

现在想象 titleDivView 和 titleSettingInputView 都共享一个 pageTitle 模型。当 titleSettingInputView 调用this.model.set('titleText', 'newTitle')时,titleDivView 可以侦听this.model.on('change:titleText', ...),并在响应中适当地重新呈现自己。通过这种方式,两个完全不连接、分离的视图可以相互交互,而不会创建一个相互关联的代码错综复杂的网络。

当然,如果没有一个很方便的“ change:title”事件可以绑定,你可以自己制作,就像我上面描述的自定义“预同步”事件一样。

于 2012-07-20T00:52:46.170 回答