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 相关文章推荐
jQuery 使用手册(二)
Sep 23 Javascript
制作jquery遮罩层效果导航菜单代码分享
Dec 25 Javascript
jQuery设置和获取HTML、文本和值示例
Jul 08 Javascript
JavaScript使用slice函数获取数组部分元素的方法
Apr 06 Javascript
基于JavaScript的操作系统你听说过吗?
Jan 28 Javascript
Bootstrap 附加导航(Affix)插件实例详解
Jun 01 Javascript
js清除浏览器缓存的几种方法
Mar 15 Javascript
AngularJS select设置默认值的实现方法
Aug 25 Javascript
bootstrap table合并行数据并居中对齐效果
Oct 17 Javascript
Vue.js中对css的操作(修改)具体方式详解
Oct 30 Javascript
layui中的switch开关实现方法
Sep 03 Javascript
原生JavaScript实现五子棋游戏
Nov 09 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
PHP3 safe_mode 失效漏洞
2006/10/09 PHP
详解php伪造Referer请求反盗链资源
2019/01/24 PHP
CI(CodeIgniter)框架中URL特殊字符处理与SQL注入隐患分析
2019/02/28 PHP
PHP与Perl之间知识点区别整理
2019/03/19 PHP
PHP实现常用排序算法的方法
2020/02/05 PHP
js 新浪的一个图片播放图片轮换效果代码
2008/07/15 Javascript
该如何加载google-analytics(或其他第三方)的JS
2010/05/13 Javascript
浅谈tudou土豆网首页图片延迟加载的效果
2010/06/23 Javascript
JS延迟加载(setTimeout) JS最后加载
2010/07/15 Javascript
关于JAVASCRIPT urldecode URL解码的问题
2012/01/08 Javascript
通过Javascript创建一个选择文件的对话框代码
2012/06/16 Javascript
jQuery+ajax实现无刷新级联菜单示例
2015/05/21 Javascript
JavaScript简单修改窗口大小的方法
2015/08/03 Javascript
jQuery中的一些小技巧
2017/01/18 Javascript
微信小程序 wx:for的使用实例详解
2017/04/27 Javascript
vue vuex vue-rouert后台项目——权限路由(适合初学)
2017/12/29 Javascript
vue-scroller记录滚动位置的示例代码
2018/01/17 Javascript
实例详解vue中的$root和$parent
2019/04/29 Javascript
JS实现的贪吃蛇游戏案例详解
2019/05/01 Javascript
使用Vue+Django+Ant Design做一个留言评论模块的示例代码
2020/06/01 Javascript
vue-cli4项目开启eslint保存时自动格式问题
2020/07/13 Javascript
Element InputNumber 计数器的实现示例
2020/08/03 Javascript
[04:39]显微镜下的DOTA2第十三期—Pis卡尔个人秀
2014/04/04 DOTA
[22:59]VGJ.S vs VG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
Python编程生成随机用户名及密码的方法示例
2017/05/05 Python
PyQt5实现下载进度条效果
2018/04/19 Python
对python中if语句的真假判断实例详解
2019/02/18 Python
使用OpenCV实现仿射变换—缩放功能
2019/08/29 Python
Python3.7.0 Shell添加清屏快捷键的实现示例
2020/03/23 Python
python3+openCV 获取图片中文本区域的最小外接矩形实例
2020/06/02 Python
解锁canvas导出图片跨域的N种姿势小结
2019/01/24 HTML / CSS
SCHIESSER荷兰官方网站:德国内衣专家
2020/10/09 全球购物
建筑安全责任书范本
2014/07/24 职场文书
环卫工作汇报材料
2014/10/28 职场文书
文体活动总结
2015/02/04 职场文书
CI Games宣布《堕落之王2》使用虚幻引擎5制作 预计将于2023年正式发售
2022/04/11 其他游戏