什么是双向绑定?

Chr*_*s M 160 javascript data-binding backbone.js

我已经阅读了很多,Backbone没有做双向绑定,但我并不完全理解这个概念.

有人能给我一个例子,说明双向绑定如何在MVC代码库中运行,以及它如何与Backbone无关?

McG*_*gle 231

双向绑定意味着:

  1. 当模型中的属性更新时,UI也会更新.
  2. 当UI元素更新时,更改会传播回模型.

Backbone没有#2的"烘焙"实现(尽管你当然可以使用事件监听器来实现).像Knockout这样的其他框架会自动连接双向绑定.


在Backbone中,您可以通过将视图的"render"方法绑定到其模型的"change"事件来轻松实现#1.要实现#2,您还需要向input元素添加更改侦听器,并model.set在处理程序中调用.

这是一个在Backbone中设置双向绑定的小提琴.

  • 一旦你看到它,答案是如此痛苦.非常感谢你花时间提供一个明确的答案和例子. (24认同)

chi*_*chi 44

双向绑定意味着影响模型的任何与数据相关的更改会立即传播到匹配的视图,并且视图中(例如,由用户)所做的任何更改都会立即反映在基础模型中.当应用数据发生变化时,UI也会发生变化,反之亦然.

这是构建Web应用程序的一个非常可靠的概念,因为它使"模型"抽象成为在应用程序中的任何位置使用的安全的原子数据源.比如说,如果绑定到视图的模型发生了变化,那么它的匹配UI(视图)将反映出来,无论如何.并且匹配的UI(视图)可以安全地用作收集用户输入/数据的手段,以便使应用程序数据保持最新.

从开发者的角度来看,一个好的双向绑定实现显然应该使模型和一些视图之间的连接尽可能简单.

然后说Backbone不支持双向绑定是非常不真实的:虽然不是框架的核心功能,但它可以很简单地使用Backbone的事件来执行.对于简单的情况,它需要花费一些明确的代码行; 并且对于更复杂的绑定可能变得非常危险.这是一个简单的案例(未经测试的代码,仅为了说明而动态编写):

Model = Backbone.Model.extend
  defaults:
    data: ''

View = Backbone.View.extend
  template: _.template("Edit the data: <input type='text' value='<%= data %>' />")

  events:
    # Listen for user inputs, and edit the model.
    'change input': @setData

  initialize: (options) ->
    # Listen for model's edition, and trigger UI update
    @listenTo @model, 'change:data', @render

  render: ->
    @$el.html @template(@model.attributes)
    @

  setData: (e) =>
    e.preventDefault()
    @model.set 'data', $(e.currentTarget).value()

model: new Model()
view = new View {el: $('.someEl'), model: model}
Run Code Online (Sandbox Code Playgroud)

这是原始Backbone应用程序中非常典型的模式.可以看出,它需要相当数量的(非常标准的)代码.

AngularJS和其他一些替代方案(Ember,Knockout ......)提供双向绑定作为第一公民特征.他们在一些DSL下抽象了许多边缘案例,并尽力在他们的生态系统中集成双向绑定.我们的示例使用AngularJS看起来像这样(未经测试的代码,见上文):

<div ng-app="app" ng-controller="MainCtrl">
  Edit the data:
  <input name="mymodel.data" ng-model="mymodel.data">
</div>
Run Code Online (Sandbox Code Playgroud)
angular.module('app', [])
  .controller 'MainCtrl', ($scope) ->
    $scope.mymodel = {data: ''}
Run Code Online (Sandbox Code Playgroud)

相当短!

但是,要注意一些完全成熟的双向绑定扩展确实存在于Backbone(原始的,主观的降低复杂性的顺序):Epoxy,Stickit,ModelBinder ......

例如,Epoxy的一个很酷的事情是,它允许您在模板(DOM)内或视图实现(JavaScript)中声明绑定(模型属性< - >视图的DOM元素).有些人强烈不喜欢在DOM /模板中添加"指令"(例如AngularJS所需的ng-*属性,或Ember的数据绑定属性).

以Epoxy为例,可以将原始的Backbone应用程序重新编写为类似的东西(...):

Model = Backbone.Model.extend
  defaults:
    data: ''

View = Backbone.Epoxy.View.extend
  template: _.template("Edit the data: <input type='text' />")
  # or, using the inline form: <input type='text' data-bind='value:data' />

  bindings:
    'input': 'value:data'

  render: ->
    @$el.html @template(@model.attributes)
    @

model: new Model()
view = new View {el: $('.someEl'), model: model}
Run Code Online (Sandbox Code Playgroud)

总而言之,几乎所有"主流"JS框架都支持双向绑定.它们中的一些,例如Backbone,确实需要一些额外的工作才能使它顺利运行,但这些都是相同的,并没有强制执行特定的方式来开始.所以这真的是关于你的心态.

此外,您可能对Flux感兴趣,这是一种不同的Web应用程序架构,通过循环模式促进单向绑定.它基于在任何数据更改时快速,全面地重新呈现UI组件的概念,以确保内聚性并使得更容易推理代码/数据流.在同一趋势中,您可能想要检查MVI(模型 - 视图 - 意图)的概念,例如Cycle.

  • 许多开发人员,特别是React/Flux开发人员不认为双向绑定是构建大型应用程序的安全模式. (3认同)

Jef*_*eff 25

McGarnagle有一个很好的答案,你会想接受他的,但我想我会提到(因为你问过)数据绑定是如何工作的.

它通常通过在对数据进行更改时触发事件来实现,然后这会导致更新侦听器(例如UI).

双向绑定通过执行此操作两次,需要注意确保您不会陷入事件循环(事件的更新导致另一个事件被触发).

我会把它放在评论中,但它已经很长了......


BKS*_*eon 5

类比解释

单向数据绑定

模型和视图

一种数据绑定方式:人移动双手,然后木偶手移动。

换句话说,“状态”的改变将迫使“观点”的改变——即人的改变传播到傀儡。

人移动木偶——而不是相反。

这是数据绑定的一种方式。

您可能听说过 Alpine JS、Elm、React 等流行框架中出现的“反应性”:这意味着当您更改“状态”时,“视图”会自动更改。

双向数据绑定

视图中的更改会传播回模型。

示例:人群中有人摇动骷髅的手,这迫使木偶操纵者的手做出响应 - 这就是双向数据绑定。这就是巫术魔法。(就我个人而言,我不喜欢它。您可以节省大约两秒钟的打字时间,但它有合法的用例。)

前端框架-数据绑定的应用

对于 Elm、React 等某些框架:“模型”不会自动更改:您需要附加事件处理程序来引发“状态”的更改。

其他框架提供两种方式的数据绑定 - 几乎自动为您处理更新“模型”的事件处理。基本上,它使您无需编写事件处理程序(尽管无论如何您仍然需要这样做)。

概括:

一种方式:状态的变化反映在视图中。

两种方式:除了一种方式绑定外,视图的改变也可以改变“状态”。

希望您不会感到困惑:如果您发表评论。