js双向数据绑定实现 js项目中双向数据绑定的简单实现方法
hyman 人气:0想了解js项目中双向数据绑定的简单实现方法的相关内容吗,hyman在本文为您仔细讲解js双向数据绑定实现的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:原生js实现数据双向绑定,js双向数据绑定原理,js实现双向绑定,下面大家一起来学习吧。
前言
双向数据绑定 指的是当对象的属性发生变化时能够同时改变对应的UI,反之亦然。换句话说,如果我们有一个user对象,这个对象有一个name属性,无论何时你对user.name设置了一个新值,UI也会展示这个新的值。同样的,如果UI包含一个用于数据用户名字的输入框,输入一个新值也会导致user对象的name属性发生相应的改变。
许多流行的javascript框架,像Ember.js,Angular.js或者KnockoutJS都会把双向数据绑定作为其中的主要特性来宣传。这并不意味着从头开始实现它很难,也不意味着当我们需要这种功能的时候,使用这些框架是我们唯一的选择。内部的潜在思想事实上是相当基础的,实现它可以归纳为以下三点:
- 我们需要一种方式确定哪个UI元素绑定在哪个属性上。
- 我们需要监控属性和UI的变化
- 我们需要把所有绑定的对象和UI元素的变化传播出去。
发布订阅者模式
发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。
订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event Channel),当发布者(Publisher)发布该事件(Publish Event)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。
结果
调用
html 调用 端 绑定 data-bind-phone="name"
<ul> <li class="block-phone fix bd-bottom"> <label for="J_verificationPhone" data-bind-phone="tishi"><span>手机号</span></label> <input class="fix1" id="J_verificationPhone" data-bind-phone="name" name="phone" type="text" /> <button class="right J_clickTime" type="button"> <span class="award-messages-btn2 J_messagesBtn1">获取验证码</span> <span class="award-messages-btn2 J_messagesBtn2 none"><i>60</i>s后重发</span> </button> </li> <li class="block-verification fix"> <label for="J_verificationCode"><span>验证码</span></label> <input class="fix1" data-bind-code="tishi" id="J_verificationCode" data-bind-phone="name" name="verification-code" class="" type="" /> </li> </ul>
js 调用 看下面代码注释
/** * function verficationCallback 回调方法 * [$btn1 description] * data-bind-phone="name" * @ message {[type]} 发生变化的字段phone * @ prop_name {[type]} 字段的value name * @ target {[type]} 目标jsdom对象; * @ targetValue {[type]} 目标jsdom对象的value */// 监听回调函数,函数会拿到targetvalue 的值, target js dom对象,便于对变化的字段进行操作!!! var User= require('../../entry/module/twoWayAudio.js'); var phone = new User('phone',verficationCallback); function verficationCallback(message,prop_name,target,targetValue){ }
引入的源代码 twoWayAudio
function DataBinder(object_id,verficationCallback){ // 创建一个简单的pubSub对象 var pubSub = { callbacks: {}, on: function(msg,callback) { this.callbacks[msg] = this.callbacks[msg] || []; this.callbacks[msg].push(callback); }, publish: function(msg) { \ this.callbacks[msg] = this.callbacks[msg] || []; for (var i = 0,len = this.callbacks[msg].length; i < len; i++) { this.callbacks[msg][i].apply(this,arguments); }; } }, data_attr = "data-bind-" + object_id, message = object_id + ":change", changeHandler = function(event) { var target = event.target || event.srcElement, // IE8兼容 prop_name = target.getAttribute(data_attr); if (prop_name && prop_name !== "") { if(verficationCallback){ var targetValue = target.value; verficationCallback (message,prop_name,target,targetValue); } pubSub.publish(message,prop_name,target.value); } }; // 监听事件变化,并代理到pubSub if (document.addEventListener) { document.addEventListener("keyup",changeHandler,false); } else{ // IE8使用attachEvent而不是addEventListenter document.attachEvent("onkeyup",changeHandler); }; // pubSub将变化传播到所有绑定元素 pubSub.on(message,function(event,prop_name,new_val){ var elements = document.querySelectorAll("[" + data_attr + "=" +prop_name + "]"), tag_name; for (var i = 0,len = elements.length; i < len; i++) { tag_name = elements[i].tagName.toLowerCase(); if (tag_name === "input" || tag_name === "textarea" || tag_name === "select") { elements[i].value = new_val; } else{ elements[i].innerHTML = new_val; }; }; }) return pubSub; } function User(uid,verficationCallback) { var binder = new DataBinder(uid,verficationCallback), user = { attribute : {}, // 属性设置器使用数据绑定器pubSub来发布 set : function(attr_name,val) { this.attribute[attr_name] = val; binder.publish(uid + ":change",attr_name,val,this); }, get : function(attr_name) { return this.attribute[attr_name]; }, _binder : binder }; binder.on(uid + ":change",function(event,attr_name,new_val,initiator) { if (initiator !== user) { user.set(attr_name,new_val); } }); return user; } module.exports = User; // phone.set( "name", "lwl" ); // phone.set( "tishi", "提示" );
替代解决方案
上面只是在掩饰双向数据绑定,其实这种需求可以更简单的实现 嘿嘿
$('.block-phone #phone')[0].oninput=function(){ console.log($(this)) }
总结
加载全部内容