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 相关文章推荐
用js实现层随着内容大小动态渐变改变 推荐
Dec 19 Javascript
JS创建自定义表格具体实现
Feb 11 Javascript
jquery 使用简明教程
Mar 05 Javascript
jquery实现一个简单好用的弹出框
Sep 26 Javascript
Javascript基础教程之while语句
Jan 18 Javascript
有效提高JavaScript执行效率的几点知识
Jan 31 Javascript
angularjs+bootstrap菜单的使用示例代码
Mar 07 Javascript
jQuery实现移动端Tab选项卡效果
Mar 15 Javascript
JavaScript使用面向对象实现的拖拽功能详解
Jun 12 Javascript
Vue.use()在new Vue() 之前使用的原因浅析
Aug 26 Javascript
详解Angular cli配置过程记录
Nov 07 Javascript
React 并发功能体验(前端的并发模式)
Jul 01 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&amp;&amp;mysql)三
2006/10/09 PHP
php中ob(Output Buffer 输出缓冲)函数使用方法
2007/07/21 PHP
php学习之 认清变量的作用范围
2010/01/26 PHP
php 在文件指定行插入数据的代码
2010/05/08 PHP
php连接mssql数据库的几种方法
2013/02/21 PHP
Ext javascript建立超链接,进行事件处理的实现方法
2009/03/22 Javascript
利用JQuery和JS实现奇偶行背景颜色自定义效果
2012/11/19 Javascript
jQuery的each终止或跳过示例代码
2013/12/12 Javascript
javascript中的undefined和not defined区别示例介绍
2014/02/26 Javascript
简介JavaScript中的setDate()方法的使用
2015/06/11 Javascript
javascript去掉代码里面的注释
2015/07/24 Javascript
javascript比较语义化版本号的实现代码
2016/09/09 Javascript
关于JavaScript和jQuery的类型判断详解
2016/10/08 Javascript
jQuery动态创建元素以及追加节点的实现方法
2016/10/20 Javascript
String字符串截取的四种方式总结
2016/11/28 Javascript
收藏AngularJS中最重要的核心功能
2017/07/09 Javascript
vue.js内置组件之keep-alive组件使用
2018/07/10 Javascript
前端Electron新手入门教程详解
2019/06/21 Javascript
axios异步提交表单数据的几种方法
2019/08/11 Javascript
ElementUI 修改默认样式的几种办法(小结)
2020/07/29 Javascript
vue中实现弹出层动画效果的示例代码
2020/09/25 Javascript
nestjs返回给前端数据格式的封装实现
2021/02/22 Javascript
python队列queue模块详解
2018/04/27 Python
目前最全的python的就业方向
2018/06/05 Python
python使用参数对嵌套字典进行取值的方法
2019/04/26 Python
Python实现自定义读写分离代码实例
2019/11/16 Python
Python MySQL 日期时间格式化作为参数的操作
2020/03/02 Python
HTML5自定义属性前缀data-及dataset的使用方法(html5 新特性)
2017/08/24 HTML / CSS
毕业生自我鉴定范文
2013/11/08 职场文书
北体毕业生求职信
2014/02/28 职场文书
公司聘任书模板
2014/03/29 职场文书
中学教师师德承诺书
2014/05/23 职场文书
合作协议书模板
2014/10/10 职场文书
年会邀请函范文
2015/01/30 职场文书
大学生村官工作心得体会
2016/01/23 职场文书
MySQL如何快速创建800w条测试数据表
2022/03/17 MySQL