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 tools之tooltip
Jul 25 Javascript
jquery 页面全选框实践代码
Apr 02 Javascript
理解Javascript_02_理解undefined和null
Oct 11 Javascript
同域jQuery(跨)iframe操作DOM(实例讲解)
Dec 19 Javascript
JavaScript中提前声明变量或函数例子
Nov 12 Javascript
jquery实现的判断倒计时是否结束代码
Feb 05 Javascript
jQuery点击其他地方时菜单消失的实现方法
Apr 22 Javascript
jQuery Easyui学习教程之实现datagrid在没有数据时显示相关提示内容
Jul 09 Javascript
给Easyui-Datebox设置隐藏或者不可用的解决方法
May 26 Javascript
Vue父子组件之间的通信实例详解
Sep 28 Javascript
详解Vue实战指南之依赖注入(provide/inject)
Nov 13 Javascript
JS前端使用canvas实现物体的点选示例
Aug 05 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
解析posix与perl标准的正则表达式区别
2013/06/17 PHP
php获取服务器端mac和客户端mac的地址支持WIN/LINUX
2014/05/15 PHP
PHP链接MySQL的常用扩展函数
2014/10/23 PHP
PHP使用mysql_fetch_row查询获得数据行列表的方法
2015/03/18 PHP
php阳历转农历优化版
2016/08/08 PHP
PHP入门教程之面向对象的特性分析(继承,多态,接口,抽象类,抽象方法等)
2016/09/11 PHP
Laravel框架Eloquent ORM简介、模型建立及查询数据操作详解
2019/12/04 PHP
php设计模式之观察者模式实例详解【星际争霸游戏案例】
2020/03/30 PHP
jquery中获取元素的几种方式小结
2011/07/05 Javascript
javascript html5移动端轻松实现文件上传
2020/03/27 Javascript
JavaScript代码实现图片循环滚动效果
2020/03/19 Javascript
AngularJS教程 ng-style 指令简单示例
2016/08/03 Javascript
JS实现重新加载当前页面或者父页面的几种方法
2016/11/30 Javascript
angularjs实现上拉加载和下拉刷新数据功能
2017/06/12 Javascript
彻底解决 webpack 打包文件体积过大问题
2017/07/07 Javascript
JavaScript数据结构之单链表和循环链表
2017/11/28 Javascript
JS正则表达式封装与使用操作示例
2019/05/15 Javascript
js实现坦克大战游戏
2020/02/24 Javascript
基于JavaScript实现留言板功能
2020/03/16 Javascript
使用python将mdb数据库文件导入postgresql数据库示例
2014/02/17 Python
利用ctypes提高Python的执行速度
2016/09/09 Python
Django入门使用示例
2017/12/12 Python
在pycharm中设置显示行数的方法
2019/01/16 Python
树莓派动作捕捉抓拍存储图像脚本
2019/06/22 Python
将python运行结果保存至本地文件中的示例讲解
2019/07/11 Python
python编写简单端口扫描器
2019/09/04 Python
python Jupyter运行时间实例过程解析
2019/12/13 Python
django自定义非主键自增字段类型详解(auto increment field)
2020/03/30 Python
HelloFresh澳大利亚:订购你的美味食品盒、健康餐食
2018/03/28 全球购物
网上常见的一份Linux面试题(多项选择部分)
2015/02/07 面试题
医学生实习自荐信
2013/10/01 职场文书
关于责任的演讲稿
2014/05/20 职场文书
外贸英文求职信范文
2015/03/19 职场文书
病假证明模板
2015/06/19 职场文书
python基础之爬虫入门
2021/05/10 Python
redis复制有可能碰到的问题汇总
2022/04/03 Redis