用纯JS实现双向数据绑定

双向数据绑定指的就是,绑定对象属性的改变到用户界面的变化的能力,反之亦然。

换种说法,如果我们有一个user对象和一个name属性,一旦我们赋了一个新值给user.name,在UI上就会显示新的姓名了。同样地,如果UI包含了一个输入用户姓名的输入框,输入一个新值就应该会使user对象的name属性做出相应的改变。

  1. 我们需要一个UI元素和属性相互绑定的方法
  2. 我们需要监视属性和UI元素的变化
  3. 我们需要让所有绑定的对象和元素都能感知到变化

还是有很多方法能够实现上面的想法,有一个简单有效的方法就是使用PubSub模式。

这个思路很简单:我们使用数据特性来为HTML代码(UI元素)进行绑定,所有被绑定在一起的JavaScript对象和DOM元素都会订阅一个PubSub对象。只要JavaScript对象或者一个HTML输入元素监听到数据的变化时,就会触发绑定到PubSub对象上的事件,从而其他绑定的对象和元素都会做出相应的变化。

<h1>原生js双向绑定及其应用</h1>
<div class="js-2-1section2 col-sm-10 col-xs-10">
<div><input type="text" data-bind-1="peopleName" id="text1"/>
<!--data-bind-1="peopleName" 原生js双向绑定的格式-->
</div>
<div><input type="text" data-bind-2="killName" id="text2" />
<button class="btn btn-primary" onclick="randomGroup()">随机词组</button>
</div>
<p data-bind-1="peopleName"></p>
<p data-bind-2="killName"></p>
</div>
var DBind1 = new DBind( 1 );
var DBind2 = new DBind( 2 );//前面是变量,括号里面的是html那里填的数字
DBind1.set( "peopleName", ‘第一个‘ );
DBind2.set( "killName", ‘第二个‘ );//第一个是刚才html格式那里的变量名,第二个方框是赋值

function DataBinder( object_id ) {
// 创建一个简单的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 + ":input",
timeIn;

changeHandler = function( evt ) {
var target = evt.target || evt.srcElement, // IE8兼容
prop_name = target.getAttribute( data_attr );

if ( prop_name && prop_name !== "" ) {
clearTimeout(timeIn);
timeIn = setTimeout(function(){
pubSub.publish( message, prop_name, target.value );
},50);

}
};

// 监听事件变化,并代理到pubSub
if ( document.addEventListener ) {
document.addEventListener( "input", changeHandler, false );
} else {
// IE8使用attachEvent而不是addEventListenter
document.attachEvent( "oninput", changeHandler );
}

// pubSub将变化传播到所有绑定元素
pubSub.on( message, function( evt, 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 DBind( uid ) {
var binder = new DataBinder( uid ),

user = {
// 属性设置器使用数据绑定器pubSub来发布
attributes: {},
set: function( attr_name, val ) {
this.attributes[ attr_name ] = val;
// Use the `publish` method
binder.publish( uid + ":input", attr_name, val, this );
},
get: function( attr_name ) {
return this.attributes[ attr_name ];
},

_binder: binder
};

// Subscribe to the PubSub
binder.on( uid + ":input", function( evt, attr_name, new_val, initiator ) {
if ( initiator !== user ) {
user.set( attr_name, new_val );
}
});

return user;
}

双向绑定应用实例

function randomGroup() {
var oGroup=[];//存放所有词汇的词组、
for(var i=0;i<20;i++){
oGroup[i]={};//设置数组中的每个元素都是一个对象
}
//一个一个定义他们状态的字符串,然后在下面赋值
oGroup[0].people="降龙十八掌";
oGroup[0].killer="九阴白骨爪";
oGroup[1].people="快乐大本营";
oGroup[1].killer="天天向上";
oGroup[2].people="零花钱";
oGroup[2].killer="生活费";
oGroup[3].people="爷爷";
oGroup[3].killer="姥爷";
oGroup[4].people="同学";
oGroup[4].killer="同桌";
oGroup[5].people="小沈阳";
oGroup[5].killer="宋小宝";
oGroup[6].people="成吉思汗";
oGroup[6].killer="努尔哈赤";
oGroup[7].people="谢娜张杰";
oGroup[7].killer="邓超孙俪";
oGroup[8].people="新年";
oGroup[8].killer="跨年";
oGroup[9].people="保安";
oGroup[9].killer="保镖";
oGroup[10].people="眉毛";
oGroup[10].killer="胡须";
oGroup[11].people="端午节";
oGroup[11].killer="中秋节";
oGroup[12].people="摩托车";
oGroup[12].killer="电动车";
oGroup[13].people="高跟鞋";
oGroup[13].killer="增高鞋";
oGroup[14].people="汉堡包";
oGroup[14].killer="肉夹馍";
oGroup[15].people="牛奶";
oGroup[15].killer="豆浆";
oGroup[16].people="唇膏";
oGroup[16].killer="口红";
oGroup[17].people="公交";
oGroup[17].killer="地铁";
oGroup[18].people="结婚";
oGroup[18].killer="订婚";
oGroup[19].people="面包";
oGroup[19].killer="蛋糕";
//词汇出自——————谁是卧底的词汇大全
var oGroupNum=Math.floor(Math.random()*20);//抽取一个随机数,随机数范围跟上面数组的长度是一致的
oPeople=oGroup[oGroupNum].people;
okiller=oGroup[oGroupNum].killer;//随机数的对应下标的状态字符串赋值给这个变量。
console.log(oPeople,okiller);
DBind1.set( "peopleName", oPeople );//将上面的状态字符串赋值给input框,。这一步将在界面中直接显示出来
DBind2.set( "killName", okiller );
}

原文地址:https://www.cnblogs.com/sarah-wen/p/10837860.html

时间: 2024-11-05 12:36:31

用纯JS实现双向数据绑定的相关文章

Js原生 双向数据绑定

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Demo</title> <script> function DataBinder( object_id ) { // Create a simple PubSub object var pubSub = { callbacks: {}, on:

angularjs学习笔记--主html&amp;template html&amp;module&amp;template js、模块、控制器、双向数据绑定、过滤器

// Register the `phoneList` component on the `phoneList` module, angular. module('phoneList'). component('phoneList', {...}); // Define the `phonecatApp` module angular.module('phonecatApp', [ // ...which depends on the `phoneList` module 'phoneList'

Angular JS - 3 - Angular JS 双向数据绑定

一 .数据绑定 1. 数据绑定: 数据从一个地方A转移(传递)到另一个地方B, 而且这个操作由框架来完成2. 双向数据绑定: 数据可以从View(视图层)流向Model(模型,也就是数据), 也可以从Model流向View 视图(View): 也就是我们的页面(主要是Andular指令和表达式) 模型(Model) : 作用域对象(当前为$rootScope), 它可以包含一些属性或方法 当改变View中的数据, Model对象的对应属性也会随之改变: ng-model指令 数据从View==>

js双向数据绑定

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>双向数据绑定</title></head><body> <div id="all"> <input type="text" id="txt"> <p

vue双向数据绑定原理探究(附demo)

昨天被导师叫去研究了一下vue的双向数据绑定原理...本来以为原理的东西都非常高深,没想到vue的双向绑定真的很好理解啊...自己动手写了一个. 传送门 双向绑定的思想 双向数据绑定的思想就是数据层与UI层的同步,数据再两者之间的任一者发生变化时都会同步更新到另一者. 双向绑定的一些方法 目前,前端实现数据双向数据绑定的方法大致有以下三种: 1.发布者-订阅者模式(backbone.js) 思路:使用自定义的data属性在HTML代码中指明绑定.所有绑定起来的JavaScript对象以及DOM元

angular和vue双向数据绑定

angular和vue双向数据绑定的原理(重点是vue的双向绑定) 我在整理javascript高级程序设计的笔记的时候看到面向对象设计那章,讲到对象属性分为数据属性和访问器属性,我们平时用的js对象90%以上都只是用到数据属性;我们向来讲解下数据属性和访问器属性到底是什么? 数据属性:数据属性包含一个数据值的位置,在这个位置可以读取和写入值. 访问器属性:访问器属性不包含数据值;他们包含一对getter和setter函数在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值,在写

angularjs - 为何要双向数据绑定

最典型的场景应该属于表单 类似表单和表格之类的场景,展示与提交一般是同时存在的. 通常情况下,单向数据绑定即可解决业务需求,如数据库的内容绑定到html中展示到页面即可 但若需要设计提交功能,双向数据绑定就会发生很便捷的作用. 双向数据绑定指的是:当文本框(或其他绑定标签.控件)发生改变时,Model也会随之发生改变 这样的话.已更改的model可以立即提交无需通过繁琐的jquery获取dom和value操作 <!doctype html> <html ng-app="User

AngularJs——双向数据绑定示例

最近在做Hybird App,接触到了AngularJs,感觉用起来蛮爽的,今天share下AngularJs的核心功能之一:双向数据绑定. 我们在页面中加入一个表单: <!DOCTYPE html> <html ng-app="userInfoModule"> <head> <meta name="content-type" content="text/html; charset=UTF-8">

AngularJS入门心得2——何为双向数据绑定

前言:谁说Test工作比较轻松,最近在熟悉几个case,差点没疯.最近又是断断续续的看我的AngularJS,总觉得自己还是没有入门,可能是自己欠前端的东西太多了,看不了几行代码就有几个常用函数不熟悉的.看过了大漠的视频,算是了解了AngularJS的一些优良特性.后来准备投身<AngularJS权威教程>,跟着它走,可是一来可能自己道行不够,二来,个人觉得这本书翻译的有些生硬以及一些瑕疵,比如: (1)9.2节:在指令中适用自作用域 (2)9.2节:在指令中适用自作用域 当然,以上都是一些瑕