什么是双向绑定?

Posted

技术标签:

【中文标题】什么是双向绑定?【英文标题】:What is two way binding? 【发布时间】:2012-11-10 09:23:48 【问题描述】:

我读过很多关于 Backbone 不做双向绑定的文章,但我并不完全理解这个概念。

谁能给我一个例子,说明两种方式绑定在 MVC 代码库中如何工作,以及在 Backbone 中如何不工作?

【问题讨论】:

【参考方案1】:

双向绑定只是意味着:

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

Backbone 没有 #2 的“内置”实现(尽管您当然可以使用事件侦听器来实现)。其他框架like Knockout do wire up two-way binding automagically.


在 Backbone 中,您可以通过将视图的“渲染”方法绑定到其模型的“更改”事件轻松实现 #1。要实现#2,您还需要为输入元素添加一个更改侦听器,并在处理程序中调用model.set

Here's a Fiddle 在 Backbone 中设置了双向绑定。

【讨论】:

答案一目了然。非常感谢您花时间提供明确的答案和示例。 Firebase 附带... 3 向数据绑定 -> 视图、模型、数据库。只是觉得这很整洁。 简明扼要。 +1【参考方案2】:

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

在此基础上构建 Web 应用程序是一个非常可靠的概念,因为它使“模型”抽象成为一个安全的原子数据源,可以在应用程序的任何地方使用。比如说,如果绑定到视图的模型发生更改,那么其匹配的 UI 部分(视图)将反映这一点,无论如何。并且匹配的 UI(视图)可以安全地用作收集用户输入/数据的一种手段,从而保持应用程序数据的最新状态。

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

那么说 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

这是原始 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>
angular.module('app', [])
  .controller 'MainCtrl', ($scope) ->
    $scope.mymodel = data: ''

相当短!

但是,请注意,对于 Backbone,一些完全成熟的双向绑定扩展确实存在(以原始的、主观的复杂性递减顺序):@987654324 @、Stickit、ModelBinder……

例如,使用 Epoxy 的一个很酷的事情是,它允许您在模板 (DOM) 或视图实现 (javascript) 中声明绑定(模型属性 视图的 DOM 元素)。有些人非常不喜欢在 DOM/模板中添加“指令”(比如 AngularJS 需要的 ng-* 属性,或者 Ember 的 data-bind 属性)。

以 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

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

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

【讨论】:

许多开发人员,尤其是 React/Flux 开发人员并不认为双向绑定是构建大型应用程序的安全模式。【参考方案3】:

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

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

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

我打算把它放在评论中,但它变得很长......

【讨论】:

【参考方案4】:

其实emberjs 支持双向绑定,这是javascript MVC 框架最强大的功能之一。您可以查看它在其用户指南中提到 binding 的位置。

对于 emberjs,创建两种方式的绑定是通过创建一个以字符串 Binding 结尾的新属性,然后从全局范围指定路径:

App.wife = Ember.Object.create(
  householdIncome: 80000
);

App.husband = Ember.Object.create(
  householdIncomeBinding: 'App.wife.householdIncome'
);

App.husband.get('householdIncome'); // 80000

// Someone gets raise.
App.husband.set('householdIncome', 90000);
App.wife.get('householdIncome'); // 90000

请注意,绑定不会立即更新。 Ember 会等到您的所有应用程序代码完成运行后再同步更改,因此您可以根据需要多次更改绑定的属性,而不必担心当值是瞬态时同步绑定的开销。

希望它有助于扩展所选的原始答案。

【讨论】:

【参考方案5】:

双向数据绑定

当模型(业务逻辑)中的数据发生变化时,视图(html)会反映变化,当视图中的数据发生变化时,模型也会随之更新。

注意:这会立即自动发生,从而确保模型和视图随时更新。

为什么我们需要双向数据绑定?

双向数据绑定用于开发实时的交互式应用程序。这种类型的应用程序被称为 SPA(单页应用程序),在 Angular.js、React.js 和 Vue.js 等现代框架中开发

【讨论】:

优秀的答案,清晰的图形,但我想知道有什么好处?如果模型需要更改,请更改模型 - 并在一处完成。 @GrahamLaight 简而言之,使用双向数据绑定我们可以构建实时应用程序。意味着您无需在应用程序中将数据从一处推送和拉取到另一处。【参考方案6】:

值得一提的是,有许多不同的解决方案可以提供双向绑定,并且播放效果非常好。

我对这个模型活页夹 - https://github.com/theironcook/Backbone.ModelBinder 有过愉快的体验。这提供了合理的默认值,但还提供了许多将模型属性映射到输入元素的自定义 jquery 选择器。

github 上有更多扩展的主干扩展/插件列表

【讨论】:

以上是关于什么是双向绑定?的主要内容,如果未能解决你的问题,请参考以下文章

jquery怎么实现双向数据绑定

什么是双向绑定?

vue双向绑定原理

Angular 手动实现ngModal数据双向绑定

Vue3的双向绑定是如何实现的

浅谈Vue的双向绑定