angular双向绑定模拟探索


Posted in Javascript onDecember 26, 2016

前言
本次探索的demo是基于jquery写的,毕竟jquery提供了强大的选择器,用惯了就离不开它了!angular的双向绑定实在是有点精深,本次探索只实现了文本的双向绑定。

View-Model

先看效果:文本框输入内容,model层数据也同步过来了

angular双向绑定模拟探索

Model-View

先看效果:js改变model层数据,视图也立即随之变化

angular双向绑定模拟探索

上我的demo

<!DOCTYPE html>
<html lang="en" data-swq-app = 'app'>
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="./js/jquery-1.9.1.min.js"></script>
</head>
<body>
<input type="text" data-swq-model="name">
<input type="text" data-swq-model="age">
<div>name:<span data-swq-bind="name"></span></div>
<div>age:<span data-swq-bind="age"></span></div>
<script>
  (function(window){
    //模仿angular的双向绑定
    //需要一个发布者,也就是angular里面的$scope的存在,这里我取我的大名swq,是个对象
    //需要订阅者数据容器
    var swqArray = []; //订阅者数据容器
    var swqNamesArray = ['name','age'];  //存放订阅者标识容器,这边写死,实际上肯定需要动态获取
    window.swq ={
      scanTag : function (){
      var swqController = $('[data-swq-app]:first');
//    view层需要和model层绑定的元素进行事件绑定
      var allModelView = swqController.find('[data-swq-model]');
      allModelView.each(function(){
        $(this).on('keyup',function(event){
          var targetBind = $(this).data('swqModel');
          var value = $(this).val();
          if(targetBind && targetBind.length > 0){
            swq[targetBind] = value;
          }
        });
      });
//    model层需要劫持绑定的进行绑定
      $.each(swqNamesArray,function(index,value){
        notifyProperty(value);
      })
    }
    };
    //数据的变化需要反映到视图上,因此要监听到数据的变化,js原生的defineProperty给我们提供了监听的可能,劫持更改数据,思路有点类似前端路由的实现思路,我监听到你某个操作但是我不做你的功能,我自己定义该做的事
    function notifyProperty(name){
      Object.defineProperty(swq,name,{
        //劫持到set方法
        set : function(newValue){
          swqArray[name] = newValue;
//      实现model-view的同步
          var $target = $('[data-swq-bind = "'+name+'"],[data-swq-model = "'+name+'"]');
          if($target){
            $target.each(function(){
              var tagName = $(this)[0].tagName.toLowerCase();
              if(tagName == 'input' || tagName =='select' || tagName =='textarea'){
                $(this).val(newValue)
              }else{
                $(this).text(newValue)
              }
            })
          }
        },
        //劫持到get方法,因为get方法已经被劫持,所以比如我们劫持了swq.name,那么swq.name就没有值了,所以我们给它返回值,返回值是存在订阅者数据容器里面的
        get : function(){
          return swqArray[name];
        }
      });
    }
 
  })(window);
 
  swq.scanTag();//初始化,进行双向绑定
//  尚未实现的功能 ;
//  1.动态获取需要进行双向绑定的name
//  2.只实现了text文本的绑定,对象的绑定需要递归
//  3.脏查询机制还未实现,就是我们某些js后增加的需要双向绑定的name,没办法进行双向绑定了
//  4.angular双花括号解析表达式未实现<br>//  5.感觉还差得远,哪位大神看到有成熟的demo记得给链接!!!
 
 
</script>
</body>
</html>

demo解读

核心其实就是js原生的defineProperty。在这之前,我们需要知道,我们在给某个对象添加和获取属性和方法时其实它底层是调用了set和get方法,比如obj.name="名字",这里是调用了set方法,obj.name这里是调用了get方法。

因此,我们可以劫持js的这两个底层方法

Object.defineProperty(obj,attribute,{set:function(newVlaue){//dosomething},get:function(){//dosomething}})
obj是我们的model对象,attribute就是我们要劫持的需要双向绑定的name,set就是设置属性时底层调用的方法,get就是获取属性时底层调用的方法因为我们劫持了这两个底层方法,我们可以做我们想做的事,但是同时我们也破坏了它本身的设置和获取功能,因此我这里是把订阅者的数据都是存在一个数组里面的,我还声明了一个数组用来保存所有需要进行双向绑定的name,比较low的是我这边是写死的,实际情况下肯定是要动态获取所有需要双向绑定的name的

结言

本人小菜对前端技术很感兴趣,有大神路过给点指点,我也可以关注下各位大神的博客,希望可以学到更多的东西!!!谢谢

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript的各种节点操作实例演示代码
Jun 27 Javascript
JS的replace方法详细介绍
Nov 09 Javascript
document.createElement()用法
Mar 13 Javascript
jquery统计输入文字的个数并对其进行判断
Jan 07 Javascript
JavaScript获取浏览器信息的方法
Nov 20 Javascript
如何解决ligerUI布局时Center中的Tab高度大小
Nov 24 Javascript
js实现根据身份证号自动生成出生日期
Dec 15 Javascript
理解Angular数据双向绑定
Jan 10 Javascript
Bootstrap中glyphicons-halflings-regular.woff字体报404错notfound的解决方法
Jan 19 Javascript
基于Vue实现拖拽功能
Jul 29 Javascript
react MPA 多页配置详解
Oct 18 Javascript
vue通过v-html指令渲染的富文本无法修改样式的解决方案
May 20 Javascript
jquery Banner轮播选项卡
Dec 26 #Javascript
Javascript中常用类型的格式化方法小结
Dec 26 #Javascript
Angular的自定义指令以及实例
Dec 26 #Javascript
如何提高javascript加载速度
Dec 26 #Javascript
JS实现一次性弹窗的方法【刷新后不弹出】
Dec 26 #Javascript
javascript实现去除HTML标签的方法
Dec 26 #Javascript
解析JavaScript实现DDoS攻击原理与保护措施
Dec 26 #Javascript
You might like
Smarty+QUICKFORM小小演示
2007/02/25 PHP
解决MySQL中文输出变成问号的问题
2008/06/05 PHP
ThinkPHP使用Smarty第三方插件方法小结
2016/03/19 PHP
thinkphp3.2实现上传图片的控制器方法
2016/04/28 PHP
PHP中类属性与类静态变量的访问方法示例
2016/07/13 PHP
jQuery学习笔记[1] jQuery中的DOM操作
2010/12/03 Javascript
jquery each()源代码
2011/02/14 Javascript
YUI模块开发原理详解
2013/11/18 Javascript
子页向父页传值示例
2013/11/27 Javascript
jquery validate添加自定义验证规则(验证邮箱 邮政编码)
2013/12/04 Javascript
用js的document.write输出的广告无阻塞加载的方法
2014/06/05 Javascript
通过JS判断联网类型和连接状态的实现代码
2015/04/01 Javascript
Bootstrap表单布局
2016/07/19 Javascript
单行 JS 实现移动端金钱格式的输入规则
2017/05/22 Javascript
JavaScript数组_动力节点Java学院整理
2017/06/26 Javascript
使用Vue自定义数字键盘组件(体验度极好)
2017/12/19 Javascript
浅析Node.js非对称加密方法
2018/01/29 Javascript
Vue.js最佳实践(五招助你成为vuejs大师)
2018/05/04 Javascript
修改vue+webpack run build的路径方法
2018/09/01 Javascript
详解vue中this.$emit()的返回值是什么
2019/04/07 Javascript
详解微信小程序调用支付接口支付
2019/04/28 Javascript
Javascript 对象(object)合并操作实例分析
2019/07/30 Javascript
vue 公共列表选择组件,引用Vant-UI的样式方式
2020/11/02 Javascript
解决谷歌搜索技术文章时打不开网页问题的python脚本
2013/02/10 Python
python 多维切片之冒号和三个点的用法介绍
2018/04/19 Python
一行Python代码过滤标点符号等特殊字符
2019/08/12 Python
实习生体会的自我评价范文
2013/11/28 职场文书
物业管理毕业生的自我评价
2014/02/17 职场文书
总经理助理的职责
2014/03/14 职场文书
房屋租赁协议书范本
2014/04/10 职场文书
vue如何批量引入组件、注册和使用详解
2021/05/12 Vue.js
QT连接MYSQL数据库的详细步骤
2021/07/07 MySQL
Go语言实现Base64、Base58编码与解码
2021/07/26 Golang
MySQL对数据表已有表进行分区表的实现
2021/11/01 MySQL
javascript Number 与 Math对象的介绍
2021/11/17 Javascript
前端JS获取URL参数的4种方法总结
2022/04/05 Javascript