Vue 数据绑定的原理分析


Posted in Javascript onNovember 16, 2020

原理

其实原理很简单,就是拦截了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', '');

以上就是Vue 数据绑定的原理分析的详细内容,更多关于Vue 数据绑定的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
Jquery 插件学习实例1 插件制作说明与tableUI优化
Apr 02 Javascript
EXT窗口Window及对话框MessageBox
Jan 27 Javascript
两种方法实现文本框输入内容提示消失
Mar 17 Javascript
js实现仿百度汽车频道选择汽车图片展示实例
May 06 Javascript
jQuery聚合函数实例
May 21 Javascript
跟我学习javascript的基本类型和引用类型
Nov 16 Javascript
javascript实现查找数组中最大值方法汇总
Feb 13 Javascript
JS表格组件神器bootstrap table详解(强化版)
May 26 Javascript
利用types增强vscode中js代码提示功能详解
Jul 07 Javascript
微信小程序实现图片上传放大预览删除代码
Jun 28 Javascript
详解vue-router传参的两种方式
Sep 10 Javascript
JS document内容及样式操作完整示例
Jan 14 Javascript
Vue 使用iframe引用html页面实现vue和html页面方法的调用操作
Nov 16 #Javascript
Vue指令实现OutClick的示例
Nov 16 #Javascript
浅谈vue在html中出现{{}}的原因及解决方式
Nov 16 #Javascript
vue组件中传值EventBus的使用及注意事项说明
Nov 16 #Javascript
小程序自定义弹框效果
Nov 16 #Javascript
vuex中遇到的坑,vuex数据改变,组件中页面不渲染操作
Nov 16 #Javascript
基于Vue+Webpack拆分路由文件实现管理
Nov 16 #Javascript
You might like
php下mysql数据库操作类(改自discuz)
2010/07/03 PHP
PHP 读取大文件并显示的简单实例(推荐)
2016/08/12 PHP
PHP调用接口用post方法传送json数据的实例
2018/05/31 PHP
PHP 代码简洁之道(小结)
2019/10/16 PHP
自写简单JS判断是否已经弹出页面
2010/10/20 Javascript
JavaScript 高级篇之DOM文档,简单封装及调用、动态添加、删除样式(六)
2012/04/07 Javascript
Zero Clipboard实现浏览器复制到剪贴板的方法(多个复制按钮)
2016/03/24 Javascript
滚动条的监听与内容随着滚动条动态加载的实现
2017/02/08 Javascript
jQuery插件HighCharts绘制2D半圆环图效果示例【附demo源码下载】
2017/03/09 Javascript
vue实现全选、反选功能
2020/11/17 Javascript
js学习总结_轮播图之渐隐渐现版(实例讲解)
2017/07/17 Javascript
微信通过页面(H5)直接打开本地app的解决方法
2017/09/09 Javascript
Angular实现的内置过滤器orderBy排序与模糊查询功能示例
2017/12/29 Javascript
VUE 配置vue-devtools调试工具及安装方法
2018/09/30 Javascript
js实现每日签到功能
2018/11/29 Javascript
vue中根据时间戳判断对应的时间(今天 昨天 前天)
2019/12/20 Javascript
js实现div色块拖动录制
2020/01/16 Javascript
vuejs element table 表格添加行,修改,单独删除行,批量删除行操作
2020/07/18 Javascript
ES6字符串的扩展实例
2020/12/21 Javascript
[43:41]VP vs RNG 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.21.mp4
2020/07/19 DOTA
Python实现定时任务
2017/02/08 Python
python开发利器之ulipad的使用实践
2017/03/16 Python
python用post访问restful服务接口的方法
2018/12/07 Python
python内存管理机制原理详解
2019/08/12 Python
docker django无法访问redis容器的解决方法
2019/08/21 Python
超级实用的8个Python列表技巧
2020/08/24 Python
加拿大奢华时装品牌:Mackage
2018/01/10 全球购物
英国珠宝钟表和家居礼品精品店:David Shuttle
2018/02/24 全球购物
给护士表扬信
2014/01/19 职场文书
医学专业自荐信
2014/06/14 职场文书
小学开学标语
2014/07/01 职场文书
党员个人自我剖析材料
2014/10/08 职场文书
党性分析材料格式
2014/12/19 职场文书
安全先进个人材料
2014/12/29 职场文书
2015年妇幼保健工作总结
2015/05/19 职场文书
一文搞懂Python Sklearn库使用
2021/08/23 Python