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 RadioButtonList获取选中值
Apr 09 Javascript
Javascript异步表单提交,图片上传,兼容异步模拟ajax技术
May 10 Javascript
jQuery版Tab标签切换
Mar 16 Javascript
js获取元素到文档区域document的(横向、纵向)坐标的两种方法
May 17 Javascript
提升jQuery的性能需要做好七件事
Jan 11 Javascript
js简单正则验证汉字英文及下划线的方法
Nov 28 Javascript
js实现右键自定义菜单
Dec 03 Javascript
JQuery获取鼠标进入和离开容器的方向
Dec 29 Javascript
Vue结合原生js实现自定义组件自动生成示例
Jan 21 Javascript
如何正确理解javascript的模块化
Mar 02 Javascript
Node.js系列之安装配置与基本使用(1)
Aug 30 Javascript
深入浅出vue图片路径的实现
Sep 04 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
分享8个最佳的代码片段在线测试网站
2013/06/29 PHP
php制作动态随机验证码
2015/02/12 PHP
Yii框架实现记录日志到自定义文件的方法
2017/05/23 PHP
三个思路解决laravel上传文件报错:413 Request Entity Too Large问题
2017/11/13 PHP
基于php中echo用逗号和用点号的区别详解
2018/01/23 PHP
BOOM vs RR BO5 第四场 2.14
2021/03/10 DOTA
javascript 复杂的嵌套环境中输出单引号和双引号
2009/05/26 Javascript
用Javascript 获取页面元素的位置的代码
2009/09/25 Javascript
jQuery extend 的简单实例
2013/09/18 Javascript
document.getElementById获取控件对象为空的解决方法
2013/11/20 Javascript
IE6-IE9使用JSON、table.innerHTML所引发的问题
2015/12/22 Javascript
JS插件plupload.js实现多图上传并显示进度条
2016/11/29 Javascript
微信小程序实现图片自适应(支持多图)
2017/01/25 Javascript
AngularJs每天学习之总体介绍
2017/08/07 Javascript
nodeJs实现基于连接池连接mysql的方法示例
2018/02/10 NodeJs
angular项目中bootstrap-datetimepicker时间插件的使用示例
2018/03/15 Javascript
关于vue的语法规则检测报错问题的解决
2018/05/21 Javascript
es6函数中的作用域实例分析
2020/04/18 Javascript
基于Vue CSR的微前端实现方案实践
2020/05/27 Javascript
[01:23]一分钟告诉你 DOTA2为什么叫信仰2
2014/06/20 DOTA
让Python代码更快运行的5种方法
2015/06/21 Python
Ubuntu 下 vim 搭建python 环境 配置
2017/06/12 Python
Python模拟随机游走图形效果示例
2018/02/06 Python
django利用request id便于定位及给日志加上request_id
2018/08/26 Python
python IDLE 背景以及字体大小的修改方法
2019/07/12 Python
详解Canvas事件绑定
2018/06/27 HTML / CSS
中国综合性网上购物商城:当当(网上卖书起家)
2016/11/16 全球购物
德国滑雪和户外用品网上商店:XSPO
2019/10/30 全球购物
外企C语言笔试题
2013/11/10 面试题
编写用C语言实现的求n阶阶乘问题的递归算法
2014/10/21 面试题
办公室年终个人自我评价
2013/10/28 职场文书
计算机网络工程专业职业生涯规划书
2014/03/10 职场文书
公安民警正风肃纪剖析材料
2014/10/10 职场文书
导游词之临安白水涧
2019/11/05 职场文书
多台电脑共享文件怎么设置?多台电脑共享文件操作教程
2022/04/08 数码科技
tomcat默认最大连接数及相关调整方法
2022/05/06 Servers