如何在 JavaScript 中实现 DOM 数据绑定 [英] How to Implement DOM Data Binding in JavaScript

查看:37
本文介绍了如何在 JavaScript 中实现 DOM 数据绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请将此问题视为严格的教育问题.我仍然有兴趣听到新的答案和想法来实现这一点

Please treat this question as strictly educational. I'm still interested in hearing new answers and ideas to implement this

我将如何使用 JavaScript 实现双向数据绑定?

How would I implement bi-directional data-binding with JavaScript?

通过数据绑定到 DOM 我的意思是,例如,拥有一个带有属性 b 的 JavaScript 对象 a.然后有一个 DOM 元素(例如),当 DOM 元素改变时,a 改变,反之亦然(也就是说,我的意思是双向数据绑定).

By data binding to the DOM I mean for example, having a JavaScript object a with a property b. Then having an <input> DOM element (for example), when the DOM element changes, a changes and vice versa (that is, I mean bidirectional data binding).

这是来自 AngularJS 的图表:

Here is a diagram from AngularJS on what this looks like:

所以基本上我的 JavaScript 类似于:

So basically I have JavaScript similar to:

var a = {b:3};

然后是一个输入(或其他表单)元素,例如:

Then an input (or other form) element like:

<input type='text' value=''>

我希望输入的值是 ab 的值(例如),当输入文本改变时,我希望 ab 也改变.当 a.b 在 JavaScript 中发生变化时,输入也会发生变化.

I'd like the input's value to be a.b's value (for example), and when the input text changes, I'd like a.b to change too. When a.b changes in JavaScript, the input changes.

在纯 JavaScript 中实现此目的的一些基本技术是什么?

What are some basic techniques to accomplish this in plain JavaScript?

具体来说,我想要一个很好的答案来参考:

In specific, I'd like a good answer to refer to:

  • 如何绑定对象?
  • 如何倾听表单中的变化?
  • 是否可以通过简单的方式只在模板级别修改 HTML?我不想在 HTML 文档本身中跟踪绑定,而只想在 JavaScript 中跟踪绑定(使用 DOM 事件,并且 JavaScript 保持对所用 DOM 元素的引用).

我是 Mustache 的忠实粉丝,所以我尝试用它来制作模板.但是,我在尝试执行数据绑定本身时遇到了问题,因为 Mustache 将 HTML 作为字符串处理,所以在我得到它的结果后,我没有参考视图模型中的对象所在的位置.我能想到的唯一解决方法是使用属性修改 HTML 字符串(或创建的 DOM 树)本身.我不介意使用不同的模板引擎.

I'm a big fan of Mustache so I tried using it for templating. However, I ran into issues when trying to perform the data binding itself since Mustache processes HTML as a string so after I get its result I have no reference to where the objects in my viewmodel are. The only workaround I could think for this was modifying the HTML string (or created DOM tree) itself with attributes. I don't mind using a different templating engine.

基本上,我有一种强烈的感觉,我把手头的问题复杂化了,有一个简单的解决方案.

Basically, I got a strong feeling that I was complicating the issue at hand and there is a simple solution.

注意:请不要提供使用外部库的答案,尤其是数千行代码的答案.我使用过(并且喜欢!)AngularJS 和 KnockoutJS.我真的不想要使用框架 x"形式的答案.最理想的是,我希望未来的读者不知道如何使用许多框架来掌握如何自己实现双向数据绑定.我不希望有一个完整的答案,而是一个能传达想法的答案.

Note: Please do not provide answers that use external libraries, especially ones that are thousands of lines of code. I've used (and like!) AngularJS and KnockoutJS. I really don't want answers in the form 'use framework x'. Optimally, I'd like a future reader who doesn't know how to use many frameworks to grasp how to implement bi-directional data-binding herself. I do not expect a complete answer, but one that gets the idea across.

推荐答案

  • 如何绑定对象?
  • 如何倾听表单中的变化?

更新两个对象的抽象

我想还有其他技术,但最终我会有一个对象来保存对相关 DOM 元素的引用,并提供一个接口来协调对其自身数据及其相关元素的更新.

An abstraction that updates both objects

I suppose there are other techniques, but ultimately I'd have an object that holds reference to a related DOM element, and provides an interface that coordinates updates to its own data and its related element.

.addEventListener() 为此提供了一个非常好的界面.你可以给它一个实现 eventListener 接口的对象,它会用这个对象作为 this 值调用它的处理程序.

The .addEventListener() provides a very nice interface for this. You can give it an object that implements the eventListener interface, and it'll invoke its handlers with that object as the this value.

这使您可以自动访问元素及其相关数据.

This gives you automatic access to both the element and its related data.

原型继承是实现这一点的好方法,尽管这当然不是必需的.首先,您将创建一个构造函数来接收您的元素和一些初始数据.

Prototypal inheritance is a nice way to implement this, though not required of course. First you'd create a constructor that receives your element and some initial data.

function MyCtor(element, data) {
    this.data = data;
    this.element = element;
    element.value = data;
    element.addEventListener("change", this, false);
}

所以这里的构造函数存储新对象的属性的元素和数据.它还将 change 事件绑定到给定的 element.有趣的是,它传递了新对象而不是函数作为第二个参数.但这本身是行不通的.

So here the constructor stores the element and data on properties of the new object. It also binds a change event to the given element. The interesting thing is that it passes the new object instead of a function as the second argument. But this alone won't work.

要完成这项工作,您的对象需要实现 eventListener 接口.完成此操作所需要做的就是为对象提供一个 handleEvent() 方法.

To make this work, your object needs to implement the eventListener interface. All that's needed to accomplish this is to give the object a handleEvent() method.

这就是继承的用武之地.

That's where the inheritance comes in.

MyCtor.prototype.handleEvent = function(event) {
    switch (event.type) {
        case "change": this.change(this.element.value);
    }
};

MyCtor.prototype.change = function(value) {
    this.data = value;
    this.element.value = value;
};

有许多不同的方式可以构建它,但是对于您协调更新的示例,我决定让 change() 方法只接受一个值,并让 handleEvent 传递该值而不是事件对象.这样 change() 也可以在没有事件的情况下被调用.

There are many different ways in which this could be structured, but for your example of coordinating updates, I decided to make the change() method only accept a value, and have the handleEvent pass that value instead of the event object. This way the change() can be invoked without an event as well.

现在,当 change 事件发生时,它会更新元素和 .data 属性.当您在 JavaScript 程序中调用 .change() 时,也会发生同样的情况.

So now, when the change event happens, it'll update both the element and the .data property. And the same will happen when you call .change() in your JavaScript program.

现在您只需创建新对象,并让它执行更新.JS 代码中的更新将显示在输入上,并且输入上的更改事件将对 JS 代码可见.

Now you'd just create the new object, and let it perform updates. Updates in JS code will appear on the input, and change events on the input will be visible to the JS code.

var obj = new MyCtor(document.getElementById("foo"), "20");

// simulate some JS based changes.
var i = 0;
setInterval(function() {
    obj.change(parseInt(obj.element.value) + ++i);
}, 3000);

演示: http://jsfiddle.net/RkTMD/

这篇关于如何在 JavaScript 中实现 DOM 数据绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆