什么是双向约束?

我读了很多书,书脊不做双向绑定,但我不完全理解这个概念。

有人能给我举个例子说明一下双向绑定在 MVC 代码库中是如何工作的吗?

134805 次浏览

双向约束意味着:

  1. 当模型中的属性得到更新时,UI 也会随之更新。
  2. 当 UI 元素得到更新时,更改将传播回模型。

Backbone 没有 # 2的“固定”实现(尽管您当然可以使用事件侦听器)。其他框架 就像敲打做电线双向绑定自动


enter image description here


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

这里有一个在 Backbone 中设置了双向绑定的 Fiddle

McGarnagle 有一个很好的答案,您可能也想接受他的答案,但是我想我应该提一下(既然您问了)数据绑定是如何工作的。

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

双向绑定通过执行两次这样的操作来工作,并小心翼翼地确保您不会卡在事件循环中(事件的更新会导致触发另一个事件)。

我本来想写评论的,但是写得太长了。

值得一提的是,有许多不同的解决方案,提供双向绑定和发挥真的很好。

我有一个愉快的经验与这个模型活页夹-https://github.com/theironcook/Backbone.ModelBinder。它提供了合理的默认值,同时也提供了大量将模型属性映射到输入元素的自定义 jquery 选择器。

Github上有一个更加广泛的骨干扩展/插件列表

实际上 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 在同步更改之前等待所有应用程序代码运行完毕,这样您就可以随心所欲地更改绑定属性多次,而不必担心在值为临时值时同步绑定的开销。

希望对原答案的选择有所帮助。

双向绑定意味着影响模型的任何与数据相关的更改都是与匹配视图相关的 立即传播,而视图中的任何更改(比如用户所做的更改)都是基础模型中的 立即反映出来。当应用程序数据发生变化时,用户界面也会发生变化,反之亦然。

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

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

因此,可以说 Backbone 不具有 支持双向绑定: 虽然它不是框架的核心特性,但是可以非常简单地使用 Backbone 的 Events 来执行。对于简单的情况,它需要几行显式的代码; 对于更复杂的绑定,它可能变得相当危险。下面是一个简单的例子(未经测试的代码,为了说明而动态编写) :

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 和其他一些替代方案(微光击倒...)提供双向绑定作为第一公民特性。它们在某些 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: ''}

太短了!

但是,请注意,一些 羽翼丰满双向绑定扩展 确实存在的骨干以及(在原始,主观降低复杂性的顺序) : 环氧树脂棍子ModelBinder..。

例如,Epoxy 的一个很酷的事情是,它允许您在模板(DOM)或视图实现(JavaScript)中声明绑定(模型属性 <-> 视图的 DOM 元素)。有些人非常不喜欢在 DOM/template 中添加“指令”(比如 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,确实需要一些额外的工作来使其工作 很顺利,但是这些都是相同的,首先不强制执行特定的方法来完成它。所以这真的和你的精神状态有关。

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

双向数据绑定

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

注意: 这将立即自动地发生,从而确保模型和视图在任何时候都在更新。

enter image description here

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

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

类比解释

单向数据绑定

Model and View

单向数据绑定: 木偶师移动他的手 然后木偶响应-通过舞蹈。

换句话说,“状态”的更改将强制在“视图”中进行更改——也就是说,木偶师中的更改将传播到傀儡。人们移动木偶——而不是反过来。

这是单向数据绑定。

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

双向数据绑定

风景中的更改将传播回模型。

例子 : 人群中有人握着骨架的手,这迫使 木偶师的手作出反应——这是双向数据绑定。

巫毒魔法。

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

对于某些框架,如 Elm、 React 等: “模型”不会自动改变: 您需要附加一个事件处理程序来诱导“状态”的改变。

其他框架提供了双向数据绑定——更新“模型”的事件处理几乎是自动完成的。基本上,它可以避免您编写事件处理程序(尽管您仍然必须 算是吧这样做)。

如果有任何困惑,请发表评论,我会尽力弥补。

LemonadeJS 是另一个值得一提的微库。它有7K 字节,并且可以很好地执行双向绑定。您可以在没有依赖项或传输的情况下运行它。

<html>
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
<div id='root'></div>
<script>
let Input = function() {
let self = {
input: 'paul@beatles.com'
}
 

// Any change in the self.input will update the input and vice-versa.
let template = `<>
<h1>\{\{self.input}}</h1>
<input type='text' @bind='self.input' />
<input type='button' value='Update' onclick="self.input = 'New value'" />
</>`
 

return lemonade.element(template, self);
}


lemonade.render(Input, document.getElementById('root'));
</script>
</html>

资料来源: https://lemonadejs.net/v2