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

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

问题描述

请将此问题视为严格教育。 我仍然希望听到新的答案和想法来实现这个



tl; dr



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



数据绑定到DOM



通过数据绑定到DOM我的意思是说,有一个具有属性 b 的JavaScript对象 a 。然后,当DOM元素发生变化时,< input> DOM元素(例如), a (也就是说,我的意思是双向数据绑定)。



以下是AngularJS中的图表:





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

  var a = {b:3}; 

然后输入(或其他窗体)元素,如:

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

我希望输入的值为 ab 的值(例如),当输入的文本发生变化时,我想要 ab 也改变。



问题


$ b当$ ab $ b

在简单的JavaScript中有什么基本的技巧来实现?



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




  • 如何对对象进行约束工作?

  • 如何倾听表单中的更改可能有效?

  • 可以以简单的方式只在模板级别修改HTML吗?我不想跟踪HTML文档本身的绑定,但只能在JavaScript中(DOM事件和JavaScript保持对所使用的DOM元素的引用)。



我试过了什么?



我是Mustache的大粉丝,所以我试着用它进行模板化。然而,当我尝试执行数据绑定本身时遇到问题,因为Mustache将HTML作为字符串处理,所以在我得到结果后,我没有参考我的viewmodel中的对象的位置。我可以想到的唯一的解决方法是使用属性修改HTML字符串(或创建的DOM树)本身。我不介意使用不同的模板引擎。



基本上,我有一个强烈的感觉,我正在使手头的问题复杂化,有一个简单的解决方案。 p>

注意:请不要提供使用外部库的答案,特别是数千行代码。我已经(和喜欢!)AngularJS和KnockoutJS。我真的不希望以use framework x的形式提供答案。最好的,我希望未来的读者不知道如何使用许多框架来掌握如何实现双向数据绑定。我不希望有一个完整的答案,而是一个可以理解的想法。

解决方案



  • 如何绑定对象的工作?

  • 如何听取更改的形式可能会工作?

  • <



更新两个对象的抽象



我想有其他的技术,但是最终我会有一个对象,它持有相关的DOM元素的引用,并提供一个接口来协调自己的数据及其相关元素的更新。



.addEventListener()为此提供了一个非常好的界面。您可以给它一个实现 eventListener 接口的对象,它将使用该对象调用其处理程序作为



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



定义对象



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

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

所以这里构造函数将元素和数据存储在新对象的属性上。它还将更改事件绑定到给定的元素。有趣的是它传递新对象而不是函数作为第二个参数。



实现 eventListener interface



为了使这个工作,你的对象需要实现 eventListener 接口。完成这一切所需要的是给对象一个 handleEvent()方法。



这是继承的地方。

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

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

有很多不同的方式可以进行结构化,但是对于协调更新的例子,我决定使 change()方法只接受一个值,并将 handleEvent 通过该值而不是事件目的。这样就可以调用 change()而不需要事件。



所以现在,当code>更改事件发生,它将更新元素和 .data 属性。当您在JavaScript程序中调用 .change()时也会发生这种情况。



使用代码< h2>

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

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

//模拟一些基于JS的更改。
var i = 0;
setInterval(function(){
obj.change(parseInt(obj.element.value)+ ++ i);
},3000);

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


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

tl;dr

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

Data Binding to the DOM

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).

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

So basically I have JavaScript similar to:

var a = {b:3};

Then an input (or other form) element like:

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

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.

The Question

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

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

  • How would binding work for objects?
  • How listening to change in the form might work?
  • Is it possible in a simple way to only have the HTML modified on the template level? I'd like to not keep track of the binding in the HTML document itself but only in JavaScript (with DOM events, and JavaScript keeping reference to the DOM elements used).

What have I tried?

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.

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.

解决方案

  • How would binding work for objects?
  • How listening to change in the form might work?

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.

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.

Defining your object

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);
}

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.

Implementing the eventListener interface

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;
};

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.

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.

Using the code

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);

DEMO: http://jsfiddle.net/RkTMD/

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

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