Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
217 views
in Technique[技术] by (71.8m points)

javascript - 如何在JavaScript中实现DOM数据绑定(How to Implement DOM Data Binding in JavaScript)

Please treat this question as strictly educational.

(请将此问题视为严格教育。)

I'm still interested in hearing new answers and ideas to implement this

(我仍然有兴趣听取新的答案和想法来实现这一点)

tl;dr(TL;博士)

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

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

Data Binding to the DOM(数据绑定到DOM)

By data binding to the DOM I mean for example, having a JavaScript object a with a property b .

(通过数据绑定到DOM,我的意思是,例如,拥有a带有属性b的JavaScript对象。)

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

(然后具有<input> DOM元素(例如),当DOM元素的变化, a变化,反之亦然(即,我的意思是双向数据绑定)。)

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

(以下是AngularJS的示意图:)

双向数据绑定

So basically I have JavaScript similar to:

(所以基本上我有类似的JavaScript:)

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 ab 's value (for example), and when the input text changes, I'd like ab to change too.

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

When ab changes in JavaScript, the input changes.

(当ab在JavaScript中发生变化时,输入会发生变化。)

The Question(问题)

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

(在纯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?

    (是否有可能以简单的方式仅在模板级别修改HTML?)

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

    (我想不跟踪HTML文档本身的绑定,而只是跟踪JavaScript(使用DOM事件,并且JavaScript保持对所使用的DOM元素的引用)。)

What have I tried?(我试过了什么?)

I'm a big fan of Mustache so I tried using it for templating.

(我是Mustache的忠实粉丝,所以我尝试用它来模板化。)

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.

(但是,当我尝试执行数据绑定本身时遇到了问题,因为Mustache将HTML作为字符串处理,因此在得到结果之后我没有引用viewmodel中对象的位置。)

The only workaround I could think for this was modifying the HTML string (or created DOM tree) itself with attributes.

(我能想到的唯一解决方法是使用属性修改HTML字符串(或创建DOM树)本身。)

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.

(我已经使用了(并且喜欢!)AngularJS和KnockoutJS。)

I really don't want answers in the form 'use framework x'.

(我真的不想要“使用框架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.

(我不希望得到一个完整的答案,而是一个能够理解这个想法的答案。)

  ask by Benjamin Gruenbaum translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
  • 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.

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

The .addEventListener() provides a very nice interface for this.

(.addEventListener()为此提供了一个非常好的接口。)

You can give it an object that implements the eventListener interface, and it'll invoke its handlers with that object as the this value.

(您可以为它提供一个实现eventListener接口的对象,并且它将使用该对象作为this值调用其处理程序。)

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 .

(它还将change事件绑定到给定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(实现eventListener接口)

To make this work, your object needs to implement the eventListener interface.

(要使其工作,您的对象需要实现eventListener接口。)

All that's needed to accomplish this is to give the object a handleEvent() method.

(完成此任务所需要的只是为对象提供handleEvent()方法。)

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.

(有许多不同的方式可以构建它,但是对于协调更新的示例,我决定使change()方法只接受一个值,并让handleEvent传递该值而不是事件对象。)

This way the change() can be invoked without an event as well.

(这样,也可以在没有事件的情况下调用change() 。)

So now, when the change event happens, it'll update both the element and the .data property.

(所以现在,当change事件发生时,它将更新元素和.data属性。)

And the same will happen when you call .change() in your JavaScript program.

(当您在JavaScript程序中调用.change()时也会发生同样的情况。)

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.

(JS代码中的更新将出现在输入中,并且JS代码可以看到输入上的更改事件。)

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/

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...