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 06 Javascript
js中的前绑定和后绑定详解
Aug 01 Javascript
js中将String转换为number以便比较
Jul 08 Javascript
JavaScript函数详解
Nov 17 Javascript
jQuery基于扩展实现的倒计时效果
May 14 Javascript
JS控制弹出悬浮窗口(一览画面)的实例代码
May 30 Javascript
JavaScript操作表单实例讲解(上)
Jun 20 Javascript
javascript 数组去重复(在线去重工具)
Dec 17 Javascript
详解HTML5 使用video标签实现选择摄像头功能
Oct 25 Javascript
新手必须知的Node.js 4个JavaScript基本概念
Sep 16 Javascript
Web安全之XSS攻击与防御小结
Dec 13 Javascript
node.js微信小程序配置消息推送的实现
Feb 13 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树型结构(无限分类)数据库设计的2种方式实例
2014/07/15 PHP
php实现在线考试系统【附源码】
2018/09/18 PHP
php+js实现的无刷新下载文件功能示例
2019/08/23 PHP
JS getStyle获取最终样式函数代码
2010/04/01 Javascript
js给dropdownlist添加选项的小例子
2013/03/04 Javascript
toggle一个div显示或隐藏且可扩展成自定义下拉框
2013/09/12 Javascript
JS滚轮事件onmousewheel使用介绍
2013/11/01 Javascript
AngularJS语法详解(续)
2015/01/23 Javascript
JS实现跟随鼠标的链接文字提示框效果
2015/08/06 Javascript
谈谈我对JavaScript原型和闭包系列理解(随手笔记6)
2015/12/20 Javascript
jQuery弹出下拉列表插件(实现kindeditor的@功能)
2016/08/16 Javascript
JS树形菜单组件Bootstrap TreeView使用方法详解
2016/12/21 Javascript
JavaScript实现获取select下拉框中第一个值的方法
2018/02/06 Javascript
React Native基础入门之调试React Native应用的一小步
2018/07/02 Javascript
vue实现移动端H5数字键盘组件使用详解
2020/08/25 Javascript
JavaScript实现轮播图效果
2020/10/30 Javascript
Python语言技巧之三元运算符使用介绍
2013/03/04 Python
python实现计算资源图标crc值的方法
2014/10/05 Python
Flask框架Jinjia模板常用语法总结
2018/07/19 Python
Python图像处理实现两幅图像合成一幅图像的方法【测试可用】
2019/01/04 Python
TensorFlow Saver:保存和读取模型参数.ckpt实例
2020/02/10 Python
python用什么编辑器进行项目开发
2020/06/17 Python
基于Python正确读取资源文件
2020/09/14 Python
Python3+RIDE+RobotFramework自动化测试框架搭建过程详解
2020/09/23 Python
德国在线订购鲜花:Fleurop
2018/08/25 全球购物
Yves Rocher伊夫·黎雪美国官网:法国始创植物美肌1959
2019/01/09 全球购物
沃尔玛加拿大:Walmart.ca
2020/03/02 全球购物
武汉瑞得软件笔试题
2015/10/27 面试题
小学三八妇女节活动方案
2014/03/16 职场文书
幼儿园六一活动总结
2014/08/27 职场文书
大学生交通专业求职信
2014/09/01 职场文书
基层干部个人对照检查及整改措施
2014/10/28 职场文书
离婚起诉状范本
2015/05/19 职场文书
涨工资申请书应该怎么写?
2019/07/08 职场文书
不知如何爱孩子,这些方法教会您
2019/08/06 职场文书
MYSQL中文乱码问题的解决方案
2022/06/14 MySQL