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 相关文章推荐
心扬JS分页函数代码
Sep 10 Javascript
js中字符替换函数String.replace()使用技巧
Aug 14 Javascript
导航跟随滚动条置顶移动示例代码
Sep 11 Javascript
JS获取当前网址、主机地址项目根路径
Nov 19 Javascript
jquery插件jTimer(jquery定时器)使用方法
Dec 23 Javascript
键盘上一张下一张兼容IE/google/firefox等浏览器
Jan 28 Javascript
jQuery中next()方法用法实例
Jan 07 Javascript
JavaScript制作windows经典扫雷小游戏
Mar 31 Javascript
使用do...while的方法输入一个月中所有的周日(实例代码)
Jul 22 Javascript
今天,小程序正式支持 SVG
Apr 20 Javascript
vuex的使用和简易实现
Jan 07 Vue.js
JS实现简单的九宫格抽奖
Jun 28 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
PHP页面间传递参数实例代码
2008/06/05 PHP
用PHP实现读取和编写XML DOM代码
2010/04/07 PHP
php Notice: Undefined index 错误提示解决方法
2010/08/29 PHP
php遍历所有文件及文件夹的方法深入解析
2013/06/08 PHP
利用PHP如何统计Nginx日志的User Agent数据
2019/03/06 PHP
跟着Jquery API学Jquery之一 选择器
2010/04/07 Javascript
Array.prototype 的泛型应用分析
2010/04/30 Javascript
基于jquery的固定表头和列头的代码
2012/05/03 Javascript
jquery 按钮状态效果 正常、移上、按下
2013/08/12 Javascript
JS获取屏幕,浏览器窗口大小,网页高度宽度(实现代码)
2013/12/17 Javascript
动态添加option及createElement使用示例
2014/01/26 Javascript
JavaScript知识点总结之如何提高性能
2016/01/15 Javascript
jQuery Easyui datagrid连续发送两次请求问题
2016/12/13 Javascript
jquery UI Datepicker时间控件冲突问题解决
2016/12/16 Javascript
nodeJS删除文件方法示例
2016/12/25 NodeJs
js 颜色选择插件
2017/01/23 Javascript
CodeMirror js代码加亮使用总结
2017/03/25 Javascript
详谈Object.defineProperty 及实现数据双向绑定
2020/07/18 Javascript
微信小程序实现简单购物车功能
2020/12/30 Javascript
python队列queue模块详解
2018/04/27 Python
详解Python中的正则表达式
2018/07/08 Python
pyspark操作MongoDB的方法步骤
2019/01/04 Python
Django的Modelforms用法简介
2019/07/27 Python
python实现把两个二维array叠加成三维array示例
2019/11/29 Python
Python 如何调试程序崩溃错误
2020/08/03 Python
html5移动端自适应布局的实现
2020/04/15 HTML / CSS
Omio波兰:全欧洲低价大巴、火车和航班搜索和比价
2018/02/16 全球购物
毕业生求职简历中的自我评价
2013/10/18 职场文书
大学生职业生涯规划书模版
2013/12/30 职场文书
店面销售职位的职责
2014/03/09 职场文书
2014年社区党建工作总结
2014/11/11 职场文书
2014年卫生工作总结
2014/11/27 职场文书
创先争优个人总结
2015/03/04 职场文书
2016社区平安家庭事迹材料
2016/02/26 职场文书
感谢信的技巧及范例
2019/05/15 职场文书
python字典的元素访问实例详解
2021/07/21 Python