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 相关文章推荐
javascript IFrame 强制刷新代码
Jul 23 Javascript
JQuery实现的在新窗口打开链接的方法小结
Apr 22 Javascript
jQuery编写widget的一些技巧分享
Oct 28 Javascript
kmock javascript 单元测试代码
Feb 06 Javascript
浅谈JSON中stringify 函数、toJosn函数和parse函数
Jan 26 Javascript
jQuery源码解读之hasClass()方法分析
Feb 20 Javascript
javascript中in运算符用法分析
Apr 28 Javascript
js获取页面description的方法
May 21 Javascript
郁闷!ionic中获取ng-model绑定的值为undefined如何解决
Aug 27 Javascript
JS实现闭包中的沙箱模式示例
Sep 07 Javascript
JavaScript实现页面中录音功能的方法
Jun 04 Javascript
Vuex modules模式下mapState/mapMutations的操作实例
Oct 17 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的一个完整SMTP类(解决邮件服务器需要验证时的问题)
2006/10/09 PHP
PHP $_SERVER详解
2009/01/16 PHP
PHP批量获取网页中所有固定种子链接的方法
2016/11/18 PHP
PHP测试框架PHPUnit组织测试操作示例
2018/05/28 PHP
document.all还是document.getElementsByName?
2006/07/21 Javascript
用于table内容排序
2006/07/21 Javascript
使用JQuery和s3captche实现一个水果名字的验证
2009/08/14 Javascript
jquery 插件学习(二)
2012/08/06 Javascript
jquery设置元素的readonly和disabled的写法
2013/09/22 Javascript
JS实现点击图片在当前页面放大并可关闭的漂亮效果
2013/10/18 Javascript
JavaScript实现九九乘法表的简单实例
2016/06/07 Javascript
JQuery遍历元素的父辈和祖先的方法
2016/09/18 Javascript
微信小程序 实例应用(记账)详解
2016/09/28 Javascript
js判断是否为空和typeof的用法(详解)
2016/10/07 Javascript
jQuery无刷新上传之uploadify简单代码
2017/01/17 Javascript
几行js代码实现自适应
2017/02/24 Javascript
Router解决跨模块下的页面跳转示例
2018/01/11 Javascript
Node.js Domain 模块实例详解
2020/03/18 Javascript
Python 元类使用说明
2009/12/18 Python
Python 详解基本语法_函数_返回值
2017/01/22 Python
python基础练习之几个简单的游戏
2017/11/10 Python
Python+matplotlib绘制不同大小和颜色散点图实例
2018/01/19 Python
关于阿里云oss获取sts凭证 app直传 python的实例
2019/08/20 Python
Python 余弦相似度与皮尔逊相关系数 计算实例
2019/12/23 Python
Raffaello Network德国:意大利拉斐尔时尚购物网
2019/05/01 全球购物
美国排名第一的泳池用品直接来源:In The Swim
2019/09/23 全球购物
易程科技软件测试笔试
2013/03/24 面试题
学生打架检讨书大全
2014/01/23 职场文书
制作部班长职位说明书
2014/02/26 职场文书
房屋继承公证书
2014/04/10 职场文书
中队活动总结
2014/08/27 职场文书
反四风对照检查材料
2014/09/22 职场文书
中国文明网向国旗敬礼寄语大全
2014/09/27 职场文书
小学教师年度个人总结
2015/02/05 职场文书
公司员工辞职信范文
2015/05/12 职场文书
聊聊golang中多个defer的执行顺序
2021/05/08 Golang