浅谈Vue数据绑定的原理


Posted in Javascript onJanuary 08, 2018

本文介绍了Vue数据绑定的原理,分享给大家,具体如下:

原理

其实原理很简单,就是拦截了Object的get/set方法,在对数据进行set (obj.aget=18) 时去重现渲染视图

实现方式有两种

方式1

定义了同名的get/set就相当于定义了age

var test = {
  _age: 18,
  get age() {
   console.log('触发get');
   //直接会this.age会进入死递归的
   return this._age;
  },
  set age(age) {
   console.log('触发set');
   this._age = age;
  }
 };

为了让test不显示多余的变量,可以把_age定义在外部

var _age = 18;
 var test = {
  get age() {
   console.log('触发get');
   //直接会this.age会进入死递归的
   return _age;
  },
  set age(age) {
   console.log('触发set');
   _age = age;
  }
 };

方式2

使用这种方式完美的解决了对象内包含多余的变量的问题

function test() {
  var _age = 18;
  Object.defineProperty(this, "age", {
   get: function () {
    console.log('触发get');
    return _age;
   },
   set: function (value) {
    console.log('触发set')
    _age = value;
   }
  });
 }
 var t = new test();
 t.age=18;

实现数据到视图的绑定

这里的渲染只是一个简单的正则替换

要实现Vue那么强大的功能还要自己实现一个模板引擎

浅谈Vue数据绑定的原理 

<div id="test">
 <p>name:</p>
 <p>age:</p>
</div>
function Element(id, initData) {
 var self = this;
 var el = document.getElementById(id);
 var templet = el.innerHTML;
 var _data = null;

 if (initData) {
 _data = {};
 for (var variable in initData) {
  _data[variable] = initData[variable];
  bind(variable, self);
 }
 }

 function bind(variable, obj) {
 Object.defineProperty(self, variable, {
  set: function (value) {
  //使用_data里的数据,避免死递归
  _data[variable] = value;
  //每次被设置新值的时候重新渲染界面
  render();
  },
  get: function () {
  return _data[variable];
  },
 });
 }

 //渲染
 function render() {
 var temp = templet;
 temp = temp.replace(/\{\{(.*)\}\}/g, function (s, t) {
  if (_data[t]) {
  return _data[t];
  }
 });
 el.innerHTML = temp;
 }

 //初始化时候手动渲染一次
 render();
}

var app = new Element('test', {
 name: 'zhangsan',
 age: 18
})

实现视图到数据的绑定

这里做一个简单的input改变的事件监听

每次渲染之后都要重新添加事件,用时间委托可以实现,但是input的focus位置不能保留

可见Vue内部的渲染和事件绑定肯定不是像这里demo写的那么简单,这里只是大致的原理(可能并不是这样的。。。)

浅谈Vue数据绑定的原理 

<div id="test">
 <input type="text" value="">
 <br>
 <span></span>
</div>
function Element(id, initData) {
 var self = this;
 var el = document.getElementById(id);
 var templet = el.innerHTML;
 var input = el.getElementsByTagName('input')[0];
 var _data = initData;

 Object.defineProperty(self, 'data', {
 set: function (value) {
  _data = value;
  render();
 },
 get: function () {
  return _data;
 },
 });

 //渲染
 function render() {
 var temp = templet;
 temp = temp.replace(/\{\{(data)\}\}/g, function (s, t) {
  return _data;
 });
 el.innerHTML = temp;

 //重新添加事件,其实应该用事件委托的
 input = el.getElementsByTagName('input')[0];
 inputchange();
 input.focus();
 }

 function inputchange() {
 if (window.attachEvent) {
  input.attachEvent("oninput", temp);
 } else if (window.addEventListener) {
  input.addEventListener("input", temp, false);
 }

 function temp() {
  self.data = input.value;
 }
 }

 //初始化时候手动渲染一次
 render();
}
var app = new Element('test', '');

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js关闭父窗口时关闭子窗口
Apr 01 Javascript
innerHTML,outerHTML,innerText,outerText的用法及区别解析
Dec 16 Javascript
js实现左侧网页tab滑动门效果代码
Sep 06 Javascript
微信小程序 使用canvas制作K线实例详解
Jan 12 Javascript
基于vue的fullpage.js单页滚动插件
Mar 20 Javascript
使用cropper.js裁剪头像的实例代码
Sep 29 Javascript
vue.js使用v-pre与v-html输出HTML操作示例
Jul 07 Javascript
Vue通过配置WebSocket并实现群聊功能
Dec 31 Javascript
原生JS实现九宫格抽奖
Sep 13 Javascript
jQuery实现简单评论区功能
Oct 26 jQuery
JS前端基于canvas给图片添加水印
Nov 11 Javascript
NestJs使用Mongoose对MongoDB操作的方法
Feb 22 Javascript
让网站自动生成章节目录索引的多个js代码
Jan 07 #Javascript
JavaScript学习总结(一) ECMAScript、BOM、DOM(核心、浏览器对象模型与文档对象模型)
Jan 07 #Javascript
Bootstrap treeview实现动态加载数据并添加快捷搜索功能
Jan 07 #Javascript
vue实现登录后页面跳转到之前页面
Jan 07 #Javascript
Nginx 配置多站点vhost 的方法
Jan 07 #Javascript
express+mockjs实现模拟后台数据发送功能
Jan 07 #Javascript
使用mock.js随机数据和使用express输出json接口的实现方法
Jan 07 #Javascript
You might like
Netflix将与CLAMP、乙一以及冲方丁等6名知名制作人合伙展开原创动画计划!
2020/03/06 日漫
php in_array 函数使用说明与in_array需要注意的地方说明
2010/04/13 PHP
Zend Framework入门教程之Zend_Registry组件用法详解
2016/12/09 PHP
Thinkphp3.2简单解决多文件上传只上传一张的问题
2017/09/26 PHP
jQuery 取值、赋值的基本方法整理
2014/03/31 Javascript
用Jquery.load载入页面后样式没了页面混乱的解决方法
2014/10/20 Javascript
javascript动画算法实例分析
2015/07/31 Javascript
js+canvas绘制矩形的方法
2016/01/28 Javascript
js获取html的span标签的值方法(超简单)
2016/07/26 Javascript
Angular2下使用pdf插件的方法详解
2017/04/29 Javascript
Node.js使用gm拼装sprite图片
2017/07/04 Javascript
vue中使用input[type=&quot;file&quot;]实现文件上传功能
2018/09/10 Javascript
JavaScript解析及序列化JSON的方法实例分析
2019/01/04 Javascript
JavaScript实现图片的放大缩小及拖拽功能示例
2019/05/14 Javascript
JavaScript Canvas编写炫彩的网页时钟
2019/10/16 Javascript
vue中解决chrome浏览器自动播放音频和MP3语音打包到线上的实现方法
2020/10/09 Javascript
使用python删除nginx缓存文件示例(python文件操作)
2014/03/26 Python
深入了解Python中pop和remove的使用方法
2018/01/09 Python
彻底搞懂Python字符编码
2018/01/23 Python
Python中循环后使用list.append()数据被覆盖问题的解决
2018/07/01 Python
Python访问MongoDB,并且转换成Dataframe的方法
2018/10/15 Python
使用python自动追踪你的快递(物流推送邮箱)
2020/03/17 Python
使用keras内置的模型进行图片预测实例
2020/06/17 Python
魔幻般冒泡背景的CSS3按钮动画
2016/02/27 HTML / CSS
html5之Canvas路径绘图、坐标变换应用实例
2012/12/26 HTML / CSS
德国玩具商店:Planet Happy DE
2021/01/16 全球购物
写出程序把一个链表中的接点顺序倒排
2014/04/28 面试题
类的返射机制中的包及核心类
2016/09/12 面试题
银行批评与自我批评
2014/02/10 职场文书
大学军训感言400字
2014/03/11 职场文书
优秀公益广告词大全
2014/03/19 职场文书
新年晚会主持词
2014/03/24 职场文书
庆祝教师节标语
2014/10/09 职场文书
2015年领导干部廉洁自律工作总结
2015/05/26 职场文书
2015秋季运动会通讯稿
2015/07/18 职场文书
vue css 相对路径导入问题级踩坑记录
2022/06/05 Vue.js