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实现非常简单实用的下拉菜单效果
Aug 27 Javascript
Ionic实现仿通讯录点击滑动及$ionicscrolldelegate使用分析
Jan 18 Javascript
JS正则表达式比较常见用法
Jan 26 Javascript
再谈Javascript中的基本类型和引用类型(推荐)
Jul 01 Javascript
Vue数据驱动模拟实现3
Jan 11 Javascript
Angular在一个页面中使用两个ng-app的方法(二)
Feb 20 Javascript
jQuery倒计时代码(超简单)
Feb 27 Javascript
javascript 开发之网页兼容各种浏览器
Sep 28 Javascript
Vue数据双向绑定的深入探究
Nov 27 Javascript
bootstrapValidator表单校验、更改状态、新增、移除校验字段的实例代码
May 19 Javascript
JavaScript实现像雪花一样的Hexaflake分形
Jul 07 Javascript
vue+openlayers绘制省市边界线
Dec 24 Vue.js
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执行速度全攻略
2006/10/09 PHP
PHP中查询SQL Server或Sybase时TEXT字段被截断的解决方法
2009/03/10 PHP
10个简化PHP开发的工具
2014/12/25 PHP
yii2中dropDownList实现二级和三级联动写法
2017/04/26 PHP
PHP基于MySQLI函数封装的数据库连接工具类【定义与用法】
2017/08/11 PHP
利用php + Laravel如何实现部署自动化详解
2017/10/11 PHP
Laravel中的chunk组块结果集处理与注意问题
2018/08/15 PHP
thinkphp5框架调用其它控制器方法 实现自定义跳转界面功能示例
2019/07/03 PHP
浅析Js(Jquery)中,字符串与JSON格式互相转换的示例(直接运行实例)
2013/07/09 Javascript
公共js在页面底部加载的注意事项介绍
2013/07/18 Javascript
浅析js中2个等号与3个等号的区别
2013/08/06 Javascript
SeaJS入门教程系列之使用SeaJS(二)
2014/03/03 Javascript
JavaScript中setUTCFullYear()方法的使用简介
2015/06/12 Javascript
谈谈基于iframe、FormData、FileReader三种无刷新上传文件的方法
2015/12/03 Javascript
JavaScript基础语法之js表达式
2016/06/07 Javascript
JavaScript 实现的checkbox经典实例分享
2016/10/16 Javascript
Bootstrap基本插件学习笔记之Alert警告框(20)
2016/12/08 Javascript
基于jQuery实现一个marquee无缝滚动的插件
2017/03/09 Javascript
bootstrap如何让dropdown menu按钮式下拉框长度一致
2017/04/10 Javascript
element-ui 时间选择器限制范围的实现(随动)
2019/01/09 Javascript
[02:53]DOTA2英雄昆卡基础教程
2013/11/25 DOTA
Python中的特殊语法:filter、map、reduce、lambda介绍
2015/04/14 Python
局域网内python socket实现windows与linux间的消息传送
2019/04/19 Python
在python中用print()输出多个格式化参数的方法
2019/07/16 Python
Python3批量移动指定文件到指定文件夹方法示例
2019/09/02 Python
python实现横向拼接图片
2020/03/23 Python
python 利用panda 实现列联表(交叉表)
2021/02/06 Python
详解基于 Canvas 手撸一个六边形能力图
2019/09/02 HTML / CSS
详解window.open被浏览器拦截的解决方案
2019/07/18 HTML / CSS
大学毕业生求职自荐信
2014/02/20 职场文书
《木笛》教学反思
2014/03/01 职场文书
党员岗位承诺书
2014/03/25 职场文书
《故乡》教学反思
2014/04/10 职场文书
环境科学专业求职信
2014/08/04 职场文书
PHP中strval()函数实例用法
2021/06/07 PHP
解决spring.thymeleaf.cache=false不起作用的问题
2022/06/10 Java/Android