一入前端深似海,从此红尘是路人系列第九弹之如何实现一个双向数据绑定

简介:

前言

简单介绍一下双向数据绑定实现的是一个什么样的东西。首先有两个东西,他们分别是:
V-视图层
M-数据层
1、视图层传向数据层:V发生改变,M也发生改变
2、数据层传向视图层:M发生改变,V也发生改变
那么接下来我们也将自己书写代码实现这样两种功能,从而实现双向数据绑定。最终实现的效果如图:
111446_ky2i_2912341.png
111517_tmiU_2912341.png
修改input框里面的内容,p标签内容也实时相对应发生改变,data里面的数据也会发生改变
111609_T6Pi_2912341.png

一、先奉献上自己完整的代码

这里我是基于jQuery进行的代码编写,其中的方法将在下面进行详细的解析


;(function($,doc,win) {
var VM = function(opt) {
  this.setting = {};
  $.extend(this.setting, opt.data);

  // 初始化VM
  this.init();
};
VM.prototype = {
  init: function() {
    this.render('input');
    this._render('p');
  },
  render: function(dom) {
    var self = this
      , data = self.setting;
    $(dom).each(function() {
      var _attr = $(this).attr('xq-model');
      if (_attr !== undefined) {
        if (data[_attr] !== undefined) {
          $(this).attr('value', data[_attr]);
          self.inputChange($(this), _attr);
        }
      }
    });
  },
  _render: function(dom) {
    var self = this;
    $(dom).each(function() {
      var val = $(this).html() || $(this).text() || $(this).val();
      if (val.indexOf('}}') !== -1 && val.indexOf('}}') !== -1) {
        val = val.replace(/^s+|{{|s+/,'');
        val = val.replace(/}}|[\s+]/g,'');
        self.labelChange(this, val);
      }
    })
  },
  labelRender: function(dom, _attr) {
    var self = this
      , data = self.setting;
    $(dom).each(function() {
      var val = $(this).attr(_attr);
      if (val !== undefined) {
        if (data[_attr] !== undefined) {
          $(this).html(data[_attr]) || $(this).text(data[_attr]) || $(this).val(data[_attr]);
        }
      }
    })
  },
  inputChange: function(_this, _attr) {
    var self = this
      , data = self.setting;
    _this.unbind('keydown');
    _this.keydown(function(){
      _this.unbind('keyup');
      _this.keyup(function() {
        var changeVal = _this.val()
          , oldVal = data[_attr];
        data[_attr] = changeVal;
        self.render('input');
        self.labelRender('p', _attr);
      })
    })
  },
  labelChange: function(_this,val) {
    var self = this
      , data = self.setting;
    if (val !== undefined) {
      if (data[val] !== undefined) {
        $(_this).html(data[val]) || $(_this).text(data[val]) || $(_this).val(data[val]);
      }
    }
    $(_this).attr(val,'')
  }
};
window.VM = VM;
})(jQuery,document,window);

二、创建自己的绑定规则

这里关于指令,我没有做作用域的包裹,比较完善的是需要用一个controller指令讲需要展示的view视图层包裹起来的。如果有想法的小伙伴们可以在最后自行去思考,接下来先直接上html代码


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>双向数据绑定</title>
</head>
<body>
    <input type="text" xq-model="msg">
    <p>
      {{ msg }}
    </p>
    <input type="text" xq-model="my">
    <p>{{ my }}</p>
</body>
<script src="js/jquery.js"></script>
<script src="js/api.js"></script>
</html>

这里我制定的双向指令是xq-model,内容的解析规则是{{}}。大家有自己喜欢的指令可以自行制定。

三、实现自己的绑定规则

我们现在需要做的就是一步一步去实现我们自己规定的一些绑定规则

首先我们需要做的第一步就是渲染出input中的xq-model指令指定的数据


/**
 * [render input框渲染]
 * @param  {[type]} dom [input]
 */
render: function(dom) {
  var self = this
    , data = self.setting;
  // 遍历dom中所有的input,搜寻带xq-model指令的input
  $(dom).each(function() {
    var _attr = $(this).attr('xq-model');
    // 判断是否有对应绑定data数据
    if (_attr !== undefined) {
      if (data[_attr] !== undefined) {
        $(this).attr('value', data[_attr]);
        // 调用input值改变方法
        self.inputChange($(this), _attr);
      }
    }
  });
}

实现inputChange方法


/**
 * [inputChange 值改变]
 * @param  {[type]} _this [当前input]
 * @param  {[type]} _attr [当前绑定对应的data数据]
 */
inputChange: function(_this, _attr) {
  var self = this
    , data = self.setting;
  // 绑定键盘事件进行监听
  _this.unbind('keydown');
  _this.keydown(function(){
    _this.unbind('keyup');
    _this.keyup(function() {
      var changeVal = _this.val()
        , oldVal = data[_attr];
      data[_attr] = changeVal;
      // 调用input框渲染方法
      self.render('input');
      // 调用标签值改变渲染方法
      self.labelRender('p', _attr);
    })
  })
}

到这里,对于input框的渲染及data数据的双向算完成了第一个了,接下来我们需要实现的便是对于标签的渲染


/**
 * [_render 标签渲染]
 * @param  {[type]} dom [element]
 */
_render: function(dom) {
  var self = this;
  // 遍历标签,拿到里面的内容
  $(dom).each(function() {
    var val = $(this).html() || $(this).text() || $(this).val();
    // 判断是否存在{{}},并截取拿到{{}} 里面的内容
    if (val.indexOf('}}') !== -1 && val.indexOf('}}') !== -1) {
      val = val.replace(/^s+|{{|s+/,'');
      val = val.replace(/}}|[\s+]/g,'');
      // 调用标签赋值方法
      self.labelChange(this, val);
    }
  })
}

实现labelChange方法


/**
 * [inputChange 值改变]
 * @param  {[type]} _this [当前input]
 * @param  {[type]} _attr [当前绑定对应的data数据]
 */
labelChange: function(_this,val) {
  var self = this
    , data = self.setting;
  if (val !== undefined) {
    if (data[val] !== undefined) {
      $(_this).html(data[val]) || $(_this).text(data[val]) || $(_this).val(data[val]);
    }
  }
  // 给当前对象绑定一个属性对应其data数据
  $(_this).attr(val,'')
}

最后实现input框输入,实时修改对应的标签的值labelRender方法


/**
 * [labelRender 标签实时渲染]
 * @param  {[type]} dom   [element]
 * @param  {[type]} _attr [当前data数据的key]
 */
labelRender: function(dom, _attr) {
  var self = this
    , data = self.setting;
  $(dom).each(function() {
    // 通过labelChange获取到对应data数据的attr属性
    var val = $(this).attr(_attr);
    if (val !== undefined) {
      if (data[_attr] !== undefined) {
        $(this).html(data[_attr]) || $(this).text(data[_attr]) || $(this).val(data[_attr]);
      }
    }
  })
}

最后我们调用一下实现好的VM


$(function() {
  new VM({
    data: {
      msg: 'hello',
      my: 'hehe'
    }
  });
})

好了,属于我们自己的一个简单的双向数据绑定至此便算是完成了,大家也可以自己将这个进行不断的完善,自己去实现一个完整的双向数据绑定。小伙伴们,加油↖(^ω^)↗

原文发布时间为:2016年11月21日
原文作者:qiangdada 

本文来源:开源中国 如需转载请联系原作者


目录
相关文章
|
2月前
|
JavaScript 前端开发 开发者
深入探讨前端框架Vue.js的数据绑定原理
在前端开发中,数据绑定是Vue.js框架的核心特性之一,它实现了视图与数据的双向绑定,极大地提高了开发效率和用户体验。本文将深入探讨Vue.js数据绑定的原理,从响应式数据、依赖追踪到虚拟DOM等方面进行详细分析,帮助读者更好地理解Vue.js框架的工作机制。
23 0
|
4月前
|
JavaScript 前端开发 开发者
JavaScript 前端框架相关:Vue.js中的双向数据绑定是如何实现的?
JavaScript 前端框架相关:Vue.js中的双向数据绑定是如何实现的?
38 1
|
前端开发 API
前端知识案例-fetch api进行数据绑定
前端知识案例-fetch api进行数据绑定
67 0
前端知识案例-fetch api进行数据绑定
|
前端开发 JavaScript
#yyds干货盘点# 前端歌谣的刷题之路-第一百零九题-双向数据绑定
#yyds干货盘点# 前端歌谣的刷题之路-第一百零九题-双向数据绑定
69 0
#yyds干货盘点# 前端歌谣的刷题之路-第一百零九题-双向数据绑定
|
前端开发
前端工作总结266-数据绑定逻辑处理
前端工作总结266-数据绑定逻辑处理
67 0
|
前端开发
前端项目实战23-前端上传文件进行数据绑定用fileList
前端项目实战23-前端上传文件进行数据绑定用fileList
55 0
|
JavaScript 前端开发
前端-vue基础8-双向数据绑定
前端-vue基础8-双向数据绑定
60 0
前端-vue基础8-双向数据绑定
|
JavaScript 前端开发
前端-vue基础9-双向数据绑定2
前端-vue基础9-双向数据绑定2
66 0
前端-vue基础9-双向数据绑定2
|
前端开发 JavaScript Java
ajax处理前端 js 与后端 ModelAndView 数据绑定
ajax处理前端 js 与后端 ModelAndView 数据绑定
286 0
|
前端开发 JavaScript iOS开发
一入前端深似海,从此红尘是路人系列第十二弹之移动端模拟IOS虚拟按钮效果
用过苹果的大家都知道,苹果公司做了一个虚拟按钮,让页面上的挂件可被拖拽并吸附到屏幕边框处,降低挂件对用户的干扰。该效果如果用JavaScript进行实现又该如何实现呢,接下来我将分享给大家。首先上一张效果图
1667 0