用原生 JS 实现双向绑定及应用实例
写在前面:
所谓的双向绑定,无非是从界面的操作能实时反映到数据,数据的变更也能实时展现到界面。angular封装了双向绑定的方法,使双向绑定变得十分简单。但是在有些场景下(比如下面那个场景),不能使用angular来实现双向绑定,需要我们使用js来实现双向绑定。
需求场景:
写了一个点击事件,当点击的时候在后台赋值了,但是在页面视图上面没有显示出来,想到要使用双向绑定来实现这个功能。因为代码之前是用js和jq写的,引入angular的话,会导致之前的代码不能用。在网上参考了一篇文章之后做出来了这个功能
ps零碎知识点:楼主踩过坑了,引用angular写的话,不能再使用JQ写代码,楼主上次代码都删的差不多了,还不能使用,最后才发现是angular和JQ冲突了,所以最好不要混着使用。
实现效果:

实现效果
点击按钮的时候,在后台赋值,然后直接在页面中显示出来,在方框里面输入值,也可以实时反映到数据。
ps:文末有demo链接,可以直接复制到本地试一试
应用:
比如实现一个在后台赋值,然后界面出现一个随机的选项,谁是卧底、狼人杀这类型的。
实现原生js过程中的三个步骤:
1.需要一个UI元素和属性相互绑定的方法(核心)
2.监视属性和UI元素的变化
3.需要让所有绑定的对象和元素都能感知到变化
实现思路:
我们使用数据特性来为HTML代码进行绑定,所有被绑定在一起的JavaScript对象和DOM元素都会订阅一个PubSub对象。只要JavaScript对象或者一个HTML输入元素监听到数据的变化时,就会触发绑定到PubSub对象上的事件,从而其他绑定的对象和元素都会做出相应的变化。
代码实现部分:
html代码部分:
| 1 2 3 4 5 6 7 8 9 10 11 | <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> | 
上面代码中data-bind-1=”peopleName” 比较重要,其他一些乱七八糟,用来实现效果的,可以不用管。
分析一下————data-bind-1=”peopleName”:
格式:data-bind-可以更改,只能是数字=”可以更改,相当于变量名”
ps:第一个地方只能更改数字,因为创建的是对象。这里的数字可以不按照顺序,我试了999都可以。
js代码双向绑定部分
js代码是封装好了的一个方法,可以按照前面几行的方式调用,代码里面有注释。
实际上以下这段代码已经实现了双向绑定,下面还有一个应用实例,感兴趣的可以看看。文末有demo链接,可以直接复制到本地试一试。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | 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; } | 
原生js双向绑定应用实例:
做了一个实现像谁是卧底中,随机抽取词汇,类似的功能。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 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 ); } | 
demo地址
以上就是用原生js实现双向绑定及其应用的所有内容了,本文主要是分享给之前不知道的小伙伴们看的,或者需要此类资料的小伙伴们。
参考链接:
用原生 JS 实现双向绑定及应用实例的更多相关文章
- 真正的原生JS数据双向绑定(实时同步)
		真正的原生JS数据双向绑定(实时同步) 接触过vue之后我感觉数据双向绑定实在是太好用了,然后就想着到底是什么原理,今天在简书上看到了一位老师的文章 js实现数据双向绑定 然后写出了我自己的代码 wi ... 
- 原生js实现双向数据绑定
		一.两个model之间的双向绑定 var o = { a: 0 } o.b = o.a + 1; console.log(o.a); // "0" console.log(o.b) ... 
- vue.js  中双向绑定的实现---初级
		1. 1 我们看到的变量,其实都不是独立的,它们都是windows对象上的属性 <!DOCTYPE html> <html lang="en"> <h ... 
- js 超浓缩 双向绑定
		绑定确实是个有趣的话题. 现在我的绑定器有了不少的功能 1. 附着在Object对象上,一切以对象为中心 2. 与页面元素进行双向绑定 3. 与任意对象绑定,主要是应用在绑定到页面元素的一些属性上,比 ... 
- [JS] 数据双向绑定原理
		通常在前端开发过程中,经常遇到需要绑定两个甚至多个元素之间的值,比如将input的值绑定到一个h1上,改变input的值,h1的文字也自动更新. <h1 id="title" ... 
- Vue.js 关于双向绑定的一些实现细节
		Vue.js 是采用 Object.defineProperty 的 getter 和 setter,并结合观察者模式来实现数据绑定的. 当把一个普通 Javascript 对象传给 Vue 实例来作 ... 
- 原生js 通用事件绑定
		/*原文地址:http://ejohn.org/blog/flexible-javascript-events/*/ http://blog.csdn.net/qi1271199790/article ... 
- 原生js给同一对象绑定多个事件
		事件监听 var son = document.querySelector(".son"); son.addEventListener('click', once1); funct ... 
- 原生 JS Ajax,GET和POST 请求实例代码
		javascript/js的ajax的GET请求代码如下所示: <script type="text/javascript"> /* 创建 XMLHttpRequest ... 
随机推荐
- Python笔记 #17# Pandas: Merge
			10 Minutes to pandas Concat df = pd.DataFrame(np.random.randn(10, 4)) print(df) # break it into piec ... 
- table中checkbox选择多行
			页面代码 <table id="addressTable" class="ui-jqgrid-htable ui-common-table table table- ... 
- 辅助模块应用(auxiliary/scanner/portscan/tcp)
			实验步骤 创建msf所需的数据库 之前我们开启msf时下面总会出现一个红色的小减号,原来是因为没有和数据库键连接,于是首先我们要手动建立一个数据库... 使用命令来实现: service postgr ... 
- 20155201 第十一周Java课堂实践
			一.表达式后缀表达式: a b x c d e / - f x + 二.mini dc MyDC.java import java.util.StringTokenizer; import java. ... 
- double保存小数点后两位
			double getRound(double a){ return (int(a * 100 + 0.5)) / 100.0; };//利用的是强制转换 
- JAVA8新特性——Lamda表达式
			JAVA9都要出来了,JAVA8新特性都没搞清楚,是不是有点掉队哦~ Lamda表达式,读作λ表达式,它实质属于函数式编程的概念,要理解函数式编程的产生目的,就要先理解匿名内部类. 先来看看传统的匿名 ... 
- Python学习札记(三十六) 面向对象编程 Object Oriented Program 7 __slots__
			参考:slots NOTE 1.动态语言灵活绑定属性及方法. #!/usr/bin/env python3 class MyClass(object): def __init__(self): pas ... 
- mongodb的安装与增删改查
			mongodb是一款分布式的文件存储的数据库,注意这两个词,分布式和文件存储.mongodb支持复制和分片,可以合理的运用空间的大小,也可以达到容灾的目的.另外文件存储也是一个特点,抛弃了传统的表的概 ... 
- Codeforces Round #307 (Div. 2) D. GukiZ and Binary Operations 矩阵快速幂优化dp
			D. GukiZ and Binary Operations time limit per test 1 second memory limit per test 256 megabytes inpu ... 
- git 撤销
			在add之前撤回文件: git checkout src/com/jay/example/testforgit/MainActivity.java 已经add的,先取消添加,再撤回 git reset ... 
