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 相关文章推荐
服务器安全设置的几个注册表设置
Jul 28 Javascript
js 页面执行时间计算代码
Mar 04 Javascript
jQuery 注意事项 与原因分析
Apr 24 Javascript
jquery判断字符输入个数(数字英文长度记为1,中文记为2,超过长度自动截取)
Oct 15 Javascript
js判断浏览器类型为ie6时不执行
Jun 15 Javascript
jQuery中end()方法用法实例
Jan 08 Javascript
javascript常用经典算法实例详解
Nov 25 Javascript
JavaScript数组去重的两种方法推荐
Apr 05 Javascript
浅谈JavaScript 标准对象
Jun 02 Javascript
JS实现HTML标签转义及反转义
Apr 14 Javascript
JS和canvas实现俄罗斯方块
Mar 14 Javascript
VUE元素的隐藏和显示(v-show指令)
Jun 23 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 INI配置文件的解析实现分析
2011/01/04 PHP
PHP中文处理 中文字符串截取(mb_substr)和获取中文字符串字数
2011/11/10 PHP
让PHP显示Facebook的粉丝数量方法
2014/01/08 PHP
3个PHP多维数组转为一维数组的方法实例
2014/03/13 PHP
Yii2中使用join、joinwith多表关联查询
2016/06/30 PHP
PHP四种排序算法实现及效率分析【冒泡排序,插入排序,选择排序和快速排序】
2018/04/27 PHP
js中有关IE版本检测
2012/01/04 Javascript
web基于浏览器的本地存储方法应用
2012/11/27 Javascript
js字符串转换成xml对象并使用技巧解读
2013/04/18 Javascript
javascript编写贪吃蛇游戏
2015/07/07 Javascript
轻松实现JavaScript图片切换
2016/01/12 Javascript
jquery实现下拉框功能效果【实例代码】
2016/05/06 Javascript
Bootstrap Table使用方法解析
2016/10/19 Javascript
JS中BOM相关知识点总结(必看篇)
2016/11/22 Javascript
jQuery纵向导航菜单效果实现方法
2016/12/19 Javascript
jQuery实现table中两列CheckBox只能选中一个的示例
2017/09/22 jQuery
浅谈Vue.nextTick 的实现方法
2017/10/25 Javascript
使用elementUI实现将图片上传到本地的示例
2018/09/04 Javascript
纯 JS 实现放大缩小拖拽功能(完整代码)
2019/11/25 Javascript
如何利用nodejs实现命令行游戏
2020/11/24 NodeJs
[02:43]DOTA2亚洲邀请赛场馆攻略——带你走进东方体育中心
2018/03/19 DOTA
python字符串连接方式汇总
2014/08/21 Python
python从入门到精通(DAY 2)
2015/12/20 Python
python 删除指定时间间隔之前的文件实例
2018/04/24 Python
python smtplib模块实现发送邮件带附件sendmail
2018/05/22 Python
Python 实现数据结构-堆栈和队列的操作方法
2019/07/17 Python
Python编写一个验证码图片数据标注GUI程序附源码
2019/12/09 Python
python使用SQLAlchemy操作MySQL
2020/01/02 Python
会计专业自我鉴定范文
2013/10/06 职场文书
研究生毕业鉴定
2014/01/29 职场文书
2014年保安个人工作总结
2014/11/13 职场文书
投标售后服务承诺书
2015/04/29 职场文书
骆驼祥子读书笔记
2015/06/26 职场文书
关于MybatisPlus配置双数据库驱动连接数据库问题
2022/01/22 Java/Android
漫画「古见同学有交流障碍症」第25卷封面公开
2022/03/21 日漫
MySQL数据管理操作示例讲解
2022/12/24 MySQL