javascript - ejemplo - getelementsbytagname
Cómo implementar el enlace de datos DOM en JavaScript (12)
- ¿Cómo funcionaría la encuadernación de objetos?
- ¿Cómo podría funcionar escuchar el cambio en la forma?
Una abstracción que actualiza ambos objetos.
Supongo que hay otras técnicas, pero en última instancia, tendría un objeto que contiene referencias a un elemento DOM relacionado y proporciona una interfaz que coordina las actualizaciones de sus propios datos y su elemento relacionado.
El .addEventListener()
proporciona una interfaz muy agradable para esto. Puede asignarle un objeto que implemente la interfaz eventListener
e invocará sus controladores con ese objeto como el valor de this
.
Esto le da acceso automático tanto al elemento como a los datos relacionados.
Definiendo tu objeto
La herencia prototípica es una buena forma de implementar esto, aunque no es obligatorio, por supuesto. Primero crearías un constructor que reciba tu elemento y algunos datos iniciales.
function MyCtor(element, data) {
this.data = data;
this.element = element;
element.value = data;
element.addEventListener("change", this, false);
}
Así que aquí el constructor almacena el elemento y los datos en las propiedades del nuevo objeto. También vincula un evento de change
al element
dado. Lo interesante es que pasa el nuevo objeto en lugar de una función como segundo argumento. Pero esto solo no funcionará.
Implementando la interfaz eventListener
Para que esto funcione, su objeto necesita implementar la interfaz eventListener
. Todo lo que se necesita para lograr esto es darle al objeto un método handleEvent()
.
Ahí es donde entra la herencia.
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;
};
Existen muchas formas diferentes de estructurar esto, pero para su ejemplo de coordinación de actualizaciones, decidí hacer que el método change()
solo acepte un valor, y que handleEvent
pase ese valor en lugar del objeto de evento. De esta manera, el change()
puede invocarse sin un evento.
Así que ahora, cuando ocurra el evento de change
, se actualizará tanto el elemento como la propiedad .data
. Y lo mismo ocurrirá cuando llame a .change()
en su programa JavaScript.
Usando el codigo
Ahora solo crearías el nuevo objeto y dejarías que realizara actualizaciones. Las actualizaciones en el código JS aparecerán en la entrada, y los eventos de cambio en la entrada serán visibles para el código 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);
Por favor, trate esta pregunta como estrictamente educativa. Todavía estoy interesado en escuchar nuevas respuestas e ideas para implementar esto.
tl; dr
¿Cómo implementaría el enlace de datos bidireccional con JavaScript?
Enlace de datos al DOM
Por vinculación de datos con el DOM me refiero, por ejemplo, a tener un objeto JavaScript a
con una propiedad b
. Luego, al tener un elemento DOM <input>
(por ejemplo), cuando el elemento DOM cambia, cambia a
elemento y viceversa (es decir, me refiero al enlace de datos bidireccional).
Aquí hay un diagrama de AngularJS sobre cómo se ve esto:
Así que básicamente tengo JavaScript similar a:
var a = {b:3};
Luego un elemento de entrada (u otra forma) como:
<input type=''text'' value=''''>
Me gustaría que el valor de la entrada sea el valor de ab
(por ejemplo), y cuando el texto de entrada cambie, también me gustaría que ab
cambie. Cuando ab
cambia en JavaScript, la entrada cambia.
La pregunta
¿Cuáles son algunas técnicas básicas para lograr esto en JavaScript simple?
En concreto, me gustaría una buena respuesta para referirme a:
- ¿Cómo funcionaría la encuadernación de objetos?
- ¿Cómo podría funcionar escuchar el cambio en la forma?
- ¿Es posible de una manera simple tener solo el HTML modificado en el nivel de la plantilla? Me gustaría no realizar un seguimiento del enlace en el documento HTML en sí, sino solo en JavaScript (con eventos DOM y JavaScript manteniendo la referencia a los elementos DOM utilizados).
¿Qué he intentado?
Soy un gran fan de Moustache, así que traté de usarlo para las plantillas. Sin embargo, tuve problemas al intentar realizar el enlace de datos en sí mismo, ya que el bigote procesa HTML como una cadena, por lo que, después de obtener su resultado, no tengo ninguna referencia a dónde se encuentran los objetos en mi modelo de vista. La única solución que podría pensar para esto fue modificar la cadena HTML (o el árbol DOM creado) con atributos. No me importa usar un motor de plantillas diferente.
Básicamente, tuve la fuerte sensación de que estaba complicando el problema en cuestión y hay una solución simple.
Nota: No proporcione respuestas que usen bibliotecas externas, especialmente las que tienen miles de líneas de código. He usado (y me gusta!) AngularJS y KnockoutJS. Realmente no quiero respuestas en la forma ''use framework x''. De manera óptima, me gustaría un futuro lector que no sepa cómo usar muchos marcos para comprender cómo implementar el enlace de datos bidireccional. No espero una respuesta completa , sino una que transmita la idea.
Ayer comencé a escribir mi propia forma de enlazar datos.
Es muy divertido jugar con él.
Creo que es hermoso y muy útil. Al menos en mis pruebas que usan Firefox y Chrome, Edge también debe funcionar. No estoy seguro de los demás, pero si es compatible con Proxy, creo que funcionará.
https://jsfiddle.net/2ozoovne/1/
<H1>Bind Context 1</H1>
<input id=''a'' data-bind=''data.test'' placeholder=''Button Text'' />
<input id=''b'' data-bind=''data.test'' placeholder=''Button Text'' />
<input type=button id=''c'' data-bind=''data.test'' />
<H1>Bind Context 2</H1>
<input id=''d'' data-bind=''data.otherTest'' placeholder=''input bind'' />
<input id=''e'' data-bind=''data.otherTest'' placeholder=''input bind'' />
<input id=''f'' data-bind=''data.test'' placeholder=''button 2 text - same var name, other context'' />
<input type=button id=''g'' data-bind=''data.test'' value=''click here!'' />
<H1>No bind data</H1>
<input id=''h'' placeholder=''not bound'' />
<input id=''i'' placeholder=''not bound''/>
<input type=button id=''j'' />
Aquí está el código:
(function(){
if ( ! ( ''SmartBind'' in window ) ) { // never run more than once
// This hack sets a "proxy" property for HTMLInputElement.value set property
var nativeHTMLInputElementValue = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, ''value'');
var newDescriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, ''value'');
newDescriptor.set=function( value ){
if ( ''settingDomBind'' in this )
return;
var hasDataBind=this.hasAttribute(''data-bind'');
if ( hasDataBind ) {
this.settingDomBind=true;
var dataBind=this.getAttribute(''data-bind'');
if ( ! this.hasAttribute(''data-bind-context-id'') ) {
console.error("Impossible to recover data-bind-context-id attribute", this, dataBind );
} else {
var bindContextId=this.getAttribute(''data-bind-context-id'');
if ( bindContextId in SmartBind.contexts ) {
var bindContext=SmartBind.contexts[bindContextId];
var dataTarget=SmartBind.getDataTarget(bindContext, dataBind);
SmartBind.setDataValue( dataTarget, value);
} else {
console.error( "Invalid data-bind-context-id attribute", this, dataBind, bindContextId );
}
}
delete this.settingDomBind;
}
nativeHTMLInputElementValue.set.bind(this)( value );
}
Object.defineProperty(HTMLInputElement.prototype, ''value'', newDescriptor);
var uid= function(){
return ''xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx''.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == ''x'' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
// SmartBind Functions
window.SmartBind={};
SmartBind.BindContext=function(){
var _data={};
var ctx = {
"id" : uid() /* Data Bind Context Id */
, "_data": _data /* Real data object */
, "mapDom": {} /* DOM Mapped objects */
, "mapDataTarget": {} /* Data Mapped objects */
}
SmartBind.contexts[ctx.id]=ctx;
ctx.data=new Proxy( _data, SmartBind.getProxyHandler(ctx, "data")) /* Proxy object to _data */
return ctx;
}
SmartBind.getDataTarget=function(bindContext, bindPath){
var bindedObject=
{ bindContext: bindContext
, bindPath: bindPath
};
var dataObj=bindContext;
var dataObjLevels=bindPath.split(''.'');
for( var i=0; i<dataObjLevels.length; i++ ) {
if ( i == dataObjLevels.length-1 ) { // last level, set value
bindedObject={ target: dataObj
, item: dataObjLevels[i]
}
} else { // digg in
if ( ! ( dataObjLevels[i] in dataObj ) ) {
console.warn("Impossible to get data target object to map bind.", bindPath, bindContext);
break;
}
dataObj=dataObj[dataObjLevels[i]];
}
}
return bindedObject ;
}
SmartBind.contexts={};
SmartBind.add=function(bindContext, domObj){
if ( typeof domObj == "undefined" ){
console.error("No DOM Object argument given ", bindContext);
return;
}
if ( ! domObj.hasAttribute(''data-bind'') ) {
console.warn("Object has no data-bind attribute", domObj);
return;
}
domObj.setAttribute("data-bind-context-id", bindContext.id);
var bindPath=domObj.getAttribute(''data-bind'');
if ( bindPath in bindContext.mapDom ) {
bindContext.mapDom[bindPath][bindContext.mapDom[bindPath].length]=domObj;
} else {
bindContext.mapDom[bindPath]=[domObj];
}
var bindTarget=SmartBind.getDataTarget(bindContext, bindPath);
bindContext.mapDataTarget[bindPath]=bindTarget;
domObj.addEventListener(''input'', function(){ SmartBind.setDataValue(bindTarget,this.value); } );
domObj.addEventListener(''change'', function(){ SmartBind.setDataValue(bindTarget, this.value); } );
}
SmartBind.setDataValue=function(bindTarget,value){
if ( ! ( ''target'' in bindTarget ) ) {
var lBindTarget=SmartBind.getDataTarget(bindTarget.bindContext, bindTarget.bindPath);
if ( ''target'' in lBindTarget ) {
bindTarget.target=lBindTarget.target;
bindTarget.item=lBindTarget.item;
} else {
console.warn("Still can''t recover the object to bind", bindTarget.bindPath );
}
}
if ( ( ''target'' in bindTarget ) ) {
bindTarget.target[bindTarget.item]=value;
}
}
SmartBind.getDataValue=function(bindTarget){
if ( ! ( ''target'' in bindTarget ) ) {
var lBindTarget=SmartBind.getDataTarget(bindTarget.bindContext, bindTarget.bindPath);
if ( ''target'' in lBindTarget ) {
bindTarget.target=lBindTarget.target;
bindTarget.item=lBindTarget.item;
} else {
console.warn("Still can''t recover the object to bind", bindTarget.bindPath );
}
}
if ( ( ''target'' in bindTarget ) ) {
return bindTarget.target[bindTarget.item];
}
}
SmartBind.getProxyHandler=function(bindContext, bindPath){
return {
get: function(target, name){
if ( name == ''__isProxy'' )
return true;
// just get the value
// console.debug("proxy get", bindPath, name, target[name]);
return target[name];
}
,
set: function(target, name, value){
target[name]=value;
bindContext.mapDataTarget[bindPath+"."+name]=value;
SmartBind.processBindToDom(bindContext, bindPath+"."+name);
// console.debug("proxy set", bindPath, name, target[name], value );
// and set all related objects with this target.name
if ( value instanceof Object) {
if ( !( name in target) || ! ( target[name].__isProxy ) ){
target[name]=new Proxy(value, SmartBind.getProxyHandler(bindContext, bindPath+''.''+name));
}
// run all tree to set proxies when necessary
var objKeys=Object.keys(value);
// console.debug("...objkeys",objKeys);
for ( var i=0; i<objKeys.length; i++ ) {
bindContext.mapDataTarget[bindPath+"."+name+"."+objKeys[i]]=target[name][objKeys[i]];
if ( typeof value[objKeys[i]] == ''undefined'' || value[objKeys[i]] == null || ! ( value[objKeys[i]] instanceof Object ) || value[objKeys[i]].__isProxy )
continue;
target[name][objKeys[i]]=new Proxy( value[objKeys[i]], SmartBind.getProxyHandler(bindContext, bindPath+''.''+name+"."+objKeys[i]));
}
// TODO it can be faster than run all items
var bindKeys=Object.keys(bindContext.mapDom);
for ( var i=0; i<bindKeys.length; i++ ) {
// console.log("test...", bindKeys[i], " for ", bindPath+"."+name);
if ( bindKeys[i].startsWith(bindPath+"."+name) ) {
// console.log("its ok, lets update dom...", bindKeys[i]);
SmartBind.processBindToDom( bindContext, bindKeys[i] );
}
}
}
return true;
}
};
}
SmartBind.processBindToDom=function(bindContext, bindPath) {
var domList=bindContext.mapDom[bindPath];
if ( typeof domList != ''undefined'' ) {
try {
for ( var i=0; i < domList.length ; i++){
var dataTarget=SmartBind.getDataTarget(bindContext, bindPath);
if ( ''target'' in dataTarget )
domList[i].value=dataTarget.target[dataTarget.item];
else
console.warn("Could not get data target", bindContext, bindPath);
}
} catch (e){
console.warn("bind fail", bindPath, bindContext, e);
}
}
}
}
})();
Entonces, para establecer, simplemente:
var bindContext=SmartBind.BindContext();
SmartBind.add(bindContext, document.getElementById(''a''));
SmartBind.add(bindContext, document.getElementById(''b''));
SmartBind.add(bindContext, document.getElementById(''c''));
var bindContext2=SmartBind.BindContext();
SmartBind.add(bindContext2, document.getElementById(''d''));
SmartBind.add(bindContext2, document.getElementById(''e''));
SmartBind.add(bindContext2, document.getElementById(''f''));
SmartBind.add(bindContext2, document.getElementById(''g''));
setTimeout( function() {
document.getElementById(''b'').value=''Via Script works too!''
}, 2000);
document.getElementById(''g'').addEventListener(''click'',function(){
bindContext2.data.test=''Set by js value''
})
Por ahora acabo de agregar el enlace de valor HTMLInputElement.
Déjame saber si sabes cómo mejorarlo.
Cambiar el valor de un elemento puede desencadenar un evento DOM . Los escuchas que responden a eventos pueden utilizarse para implementar el enlace de datos en JavaScript.
Por ejemplo:
function bindValues(id1, id2) {
const e1 = document.getElementById(id1);
const e2 = document.getElementById(id2);
e1.addEventListener(''input'', function(event) {
e2.value = event.target.value;
});
e2.addEventListener(''input'', function(event) {
e1.value = event.target.value;
});
}
Here hay un código y una demostración que muestra cómo los elementos DOM se pueden vincular entre sí o con un objeto JavaScript.
Creo que mi respuesta será más técnica, pero no diferente, ya que las otras presentan la misma cosa utilizando diferentes técnicas.
Entonces, lo primero es que la solución a este problema es el uso de un patrón de diseño conocido como "observador", que le permite desacoplar sus datos de su presentación, haciendo que el cambio en una cosa se transmita a sus oyentes, pero en este caso se hace de dos vías
Para el camino de DOM a JS
Para vincular los datos del DOM al objeto js, puede agregar un marcado en forma de atributos de data
(o clases si necesita compatibilidad), como esto:
<input type="text" data-object="a" data-property="b" id="b" class="bind" value=""/>
<input type="text" data-object="a" data-property="c" id="c" class="bind" value=""/>
<input type="text" data-object="d" data-property="e" id="e" class="bind" value=""/>
De esta manera, se puede acceder a través de js utilizando querySelectorAll
(o el antiguo amigo getElementsByClassName
por compatibilidad).
Ahora puede vincular el evento escuchando los cambios en formas: un oyente por objeto o un gran oyente al contenedor / documento. El enlace al documento / contenedor activará el evento por cada cambio que se realice en él o en su hijo, tendrá una huella de memoria más pequeña pero generará llamadas de evento.
El código se verá algo así:
//Bind to each element
var elements = document.querySelectorAll(''input[data-property]'');
function toJS(){
//Assuming `a` is in scope of the document
var obj = document[this.data.object];
obj[this.data.property] = this.value;
}
elements.forEach(function(el){
el.addEventListener(''change'', toJS, false);
}
//Bind to document
function toJS2(){
if (this.data && this.data.object) {
//Again, assuming `a` is in document''s scope
var obj = document[this.data.object];
obj[this.data.property] = this.value;
}
}
document.addEventListener(''change'', toJS2, false);
Para el modo JS do DOM.
Necesitará dos cosas: un metaobjeto que contendrá las referencias del elemento DOM de bruja está vinculado a cada objeto / atributo js y una forma de escuchar los cambios en los objetos. Básicamente es de la misma manera: debe tener una forma de escuchar los cambios en el objeto y luego vincularlo al nodo DOM, ya que su objeto "no puede tener" metadatos, necesitará otro objeto que contenga metadatos de alguna manera. que el nombre de la propiedad se asigna a las propiedades del objeto de metadatos. El código será algo así:
var a = {
b: ''foo'',
c: ''bar''
},
d = {
e: ''baz''
},
metadata = {
b: ''b'',
c: ''c'',
e: ''e''
};
function toDOM(changes){
//changes is an array of objects changed and what happened
//for now i''d recommend a polyfill as this syntax is still a proposal
changes.forEach(function(change){
var element = document.getElementById(metadata[change.name]);
element.value = change.object[change.name];
});
}
//Side note: you can also use currying to fix the second argument of the function (the toDOM method)
Object.observe(a, toDOM);
Object.observe(d, toDOM);
Espero que haya sido de ayuda.
Enlazar cualquier entrada html
<input id="element-to-bind" type="text">
define dos funciones:
function bindValue(objectToBind) {
var elemToBind = document.getElementById(objectToBind.id)
elemToBind.addEventListener("change", function() {
objectToBind.value = this.value;
})
}
function proxify(id) {
var handler = {
set: function(target, key, value, receiver) {
target[key] = value;
document.getElementById(target.id).value = value;
return Reflect.set(target, key, value);
},
}
return new Proxy({id: id}, handler);
}
utilizar las funciones:
var myObject = proxify(''element-to-bind'')
bindValue(myObject);
Entonces, decidí tirar mi propia solución en la olla. Aquí hay un violín de trabajo . Tenga en cuenta que esto solo funciona en navegadores muy modernos.
Lo que usa
Esta implementación es muy moderna: requiere un navegador (muy) moderno y los usuarios dos nuevas tecnologías:
- MutationObservers para detectar cambios en el dom (los detectores de eventos también se utilizan)
-
Object.observe
para detectar cambios en el objeto y notificar el dominio. Peligro, ya que esta respuesta ha sido escrita Oo ha sido discutido y rechazado por el ECMAScript TC, considere un polyfill .
Cómo funciona
- En el elemento, coloque un mapeo
domAttribute:objAttribute
- por ejemplobind=''textContent:name''
- Lee eso en la función dataBind. Observe los cambios tanto en el elemento como en el objeto.
- Cuando se produce un cambio, actualice el elemento relevante.
La solución
Aquí está la función dataBind
, tenga en cuenta que es solo 20 líneas de código y podría ser más corta:
function dataBind(domElement, obj) {
var bind = domElement.getAttribute("bind").split(":");
var domAttr = bind[0].trim(); // the attribute on the DOM element
var itemAttr = bind[1].trim(); // the attribute the object
// when the object changes - update the DOM
Object.observe(obj, function (change) {
domElement[domAttr] = obj[itemAttr];
});
// when the dom changes - update the object
new MutationObserver(updateObj).observe(domElement, {
attributes: true,
childList: true,
characterData: true
});
domElement.addEventListener("keyup", updateObj);
domElement.addEventListener("click",updateObj);
function updateObj(){
obj[itemAttr] = domElement[domAttr];
}
// start the cycle by taking the attribute from the object and updating it.
domElement[domAttr] = obj[itemAttr];
}
Aquí hay algo de uso:
HTML:
<div id=''projection'' bind=''textContent:name''></div>
<input type=''text'' id=''textView'' bind=''value:name'' />
JavaScript:
var obj = {
name: "Benjamin"
};
var el = document.getElementById("textView");
dataBind(el, obj);
var field = document.getElementById("projection");
dataBind(field,obj);
Aquí hay un violín de trabajo . Tenga en cuenta que esta solución es bastante genérica. Object.observe y mutación observador shimming está disponible.
Hay una implementación muy sencilla de enlace de datos bidireccional en este enlace " Enlace de datos bidireccional sencillo en JavaScript"
El enlace anterior, junto con las ideas de knockoutjs, backbone.js y agility.js, condujo a este marco MVVM ligero y rápido, ModelView.js basado en jQuery que juega muy bien con jQuery y del cual soy el autor humilde (o tal vez no tan humilde).
Reproducción de código de ejemplo a continuación (desde el enlace de la publicación del blog ):
Código de ejemplo para DataBinder
function DataBinder( object_id ) {
// Use a jQuery object as simple PubSub
var pubSub = jQuery({});
// We expect a `data` element specifying the binding
// in the form: data-bind-<object_id>="<property_name>"
var data_attr = "bind-" + object_id,
message = object_id + ":change";
// Listen to change events on elements with the data-binding attribute and proxy
// them to the PubSub, so that the change is "broadcasted" to all connected objects
jQuery( document ).on( "change", "[data-" + data_attr + "]", function( evt ) {
var $input = jQuery( this );
pubSub.trigger( message, [ $input.data( data_attr ), $input.val() ] );
});
// PubSub propagates changes to all bound elements, setting value of
// input tags or HTML content of other tags
pubSub.on( message, function( evt, prop_name, new_val ) {
jQuery( "[data-" + data_attr + "=" + prop_name + "]" ).each( function() {
var $bound = jQuery( this );
if ( $bound.is("input, textarea, select") ) {
$bound.val( new_val );
} else {
$bound.html( new_val );
}
});
});
return pubSub;
}
Para lo que concierne al objeto de JavaScript, una implementación mínima de un modelo de Usuario para este experimento podría ser lo siguiente:
function User( uid ) {
var binder = new DataBinder( uid ),
user = {
attributes: {},
// The attribute setter publish changes using the DataBinder PubSub
set: function( attr_name, val ) {
this.attributes[ attr_name ] = val;
binder.trigger( uid + ":change", [ attr_name, val, this ] );
},
get: function( attr_name ) {
return this.attributes[ attr_name ];
},
_binder: binder
};
// Subscribe to the PubSub
binder.on( uid + ":change", function( evt, attr_name, new_val, initiator ) {
if ( initiator !== user ) {
user.set( attr_name, new_val );
}
});
return user;
}
Ahora, cuando queremos vincular las propiedades de un modelo a una parte de la interfaz de usuario solo tenemos que establecer un atributo de datos apropiado en el elemento HTML correspondiente:
// javascript
var user = new User( 123 );
user.set( "name", "Wolfgang" );
<!-- html -->
<input type="number" data-bind-123="name" />
Me gustaría agregar a mi preposter. Sugiero un enfoque ligeramente diferente que le permitirá simplemente asignar un nuevo valor a su objeto sin utilizar un método. Sin embargo, se debe tener en cuenta que esto no es compatible con los navegadores especialmente antiguos e IE9 aún requiere el uso de una interfaz diferente.
Lo más notable es que mi enfoque no hace uso de eventos.
Hechiceros y Setters
Mi propuesta hace uso de la característica relativamente joven de getters y setters , particularmente solo setters. En términos generales, los mutadores nos permiten "personalizar" el comportamiento de cómo ciertas propiedades se asignan un valor y se recuperan.
Una implementación que Object.defineProperty aquí es el método Object.defineProperty . Funciona en Firefox, GoogleChrome y, creo, en IE9. No he probado otros navegadores, pero como esto es solo teórico ...
De todos modos, acepta tres parámetros. El primer parámetro es el objeto para el que desea definir una nueva propiedad, el segundo una cadena que se parece al nombre de la nueva propiedad y el último un "objeto descriptor" que proporciona información sobre el comportamiento de la nueva propiedad.
Dos descriptores particularmente interesantes son get
y set
. Un ejemplo sería el siguiente. Tenga en cuenta que el uso de estos dos prohíbe el uso de los otros 4 descriptores.
function MyCtor( bindTo ) {
// I''ll omit parameter validation here.
Object.defineProperty(this, ''value'', {
enumerable: true,
get : function ( ) {
return bindTo.value;
},
set : function ( val ) {
bindTo.value = val;
}
});
}
Ahora haciendo uso de esto se vuelve ligeramente diferente:
var obj = new MyCtor(document.getElementById(''foo'')),
i = 0;
setInterval(function() {
obj.value += ++i;
}, 3000);
Quiero enfatizar que esto solo funciona para los navegadores modernos.
Fiddle de trabajo: http://jsfiddle.net/Derija93/RkTMD/1/
Es un enlace de datos bidireccional muy simple en vainilla javascript ....
<input type="text" id="inp" onkeyup="document.getElementById(''name'').innerHTML=document.getElementById(''inp'').value;">
<div id="name">
</div>
He analizado algunos ejemplos básicos de javascript utilizando onkeypress y onchange event handlers para hacer vistas vinculantes a nuestros js y js
Aquí ejemplo plunker http://plnkr.co/edit/7hSOIFRTvqLAvdZT4Bcc?p=preview
<!DOCTYPE html>
<html>
<body>
<p>Two way binding data.</p>
<p>Binding data from view to JS</p>
<input type="text" onkeypress="myFunction()" id="myinput">
<p id="myid"></p>
<p>Binding data from js to view</p>
<input type="text" id="myid2" onkeypress="myFunction1()" oninput="myFunction1()">
<p id="myid3" onkeypress="myFunction1()" id="myinput" oninput="myFunction1()"></p>
<script>
document.getElementById(''myid2'').value="myvalue from script";
document.getElementById(''myid3'').innerHTML="myvalue from script";
function myFunction() {
document.getElementById(''myid'').innerHTML=document.getElementById(''myinput'').value;
}
document.getElementById("myinput").onchange=function(){
myFunction();
}
document.getElementById("myinput").oninput=function(){
myFunction();
}
function myFunction1() {
document.getElementById(''myid3'').innerHTML=document.getElementById(''myid2'').value;
}
</script>
</body>
</html>
Una forma sencilla de vincular una variable a una entrada (enlace bidireccional) es acceder directamente al elemento de entrada en el getter y setter:
var variable = function(element){
return {
get : function () { return element.value;},
set : function (value) { element.value = value;}
}
};
En HTML:
<input id="an-input" />
<input id="another-input" />
Y utilizar:
var myVar = new variable(document.getElementById("an-input"));
myVar.set(10);
// and another example:
var myVar2 = new variable(document.getElementById("another-input"));
myVar.set(myVar2.get());
Una forma más elegante de hacer lo anterior sin getter / setter:
var variable = function(element){
return function () {
if(arguments.length > 0)
element.value = arguments[0];
else return element.value;
}
}
Usar:
var v1 = new variable(document.getElementById("an-input"));
v1(10); // sets value to 20.
console.log(v1()); // reads value.
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<input type="text" id="demo" name="">
<p id="view"></p>
<script type="text/javascript">
var id = document.getElementById(''demo'');
var view = document.getElementById(''view'');
id.addEventListener(''input'', function(evt){
view.innerHTML = this.value;
});
</script>
</body>
</html>