Vue2.X和Vue3.0数据响应原理变化的区别


Posted in Javascript onNovember 07, 2019

defineProperty 定义对象的属性,只不过属性里的get和set实现了响应式。

常用:

  • value属性值
  • get
  • set
  • writeable 是否可写
  • enumrable 可遍历

Vue从改变一个数据到发生改变的过程

Vue2.X和Vue3.0数据响应原理变化的区别

 Vue2.X数据响应原理

创建页面,实现延时2s修改对象的值。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>LearnVue3.0</title>
</head>
<body>
  <div id="app"></div>
  <script type="text/javascript" src="test.js"></script>
  <script type="text/javascript">
    const vm = new vue();
    setTimeout(function () {
      console.log('change');
      console.log(vm.$data);
      vm.$data.a = 444;
    }, 2000);

  </script>
</body>
</html>

defineProperty 实现:

function vue() {
  this.$data = {
    a: 1
  };
  this.el = document.getElementById('app');
  this._html = "";
  this.observe(this.$data);
  this.render();
}

vue.prototype.observe = function (obj) {
  let self = this;
  let value;

  for (let key in obj) {
    value = obj[key];
    if (typeof value === 'object') {
      this.observe(value);
    } else {
      Object.defineProperty(this.$data, key, {
        get: function () {
          return value;
        },
        set: function (newvalue) {
          value = newvalue;
          self.render()
        }
      })
    }
  }
}

vue.prototype.render = function () {
  this._html = "I am " + this.$data.a;
  this.el.innerHTML = this._html;
}

在Chrome中console运行,结果页面显示: I am 444

针对数组特性化处理:

let arraypro = Array.prototype;
// 为什么要create再次创建对象,create是深拷贝,不影响之前的arraypro
let arrayob = Object.create(arraypro);
// 定义哪些方法触发更新
let arr = ["push", "pop", "shift"];

// arr里的方法,既能保持原有方法,又能触发更新
// 装饰者模式
arr.forEach(function (method, index) {
  // 对自己的push方法重写
  arrayob[method] = function () {
    let ret = arraypro[method].apply(this, arguments);
    // self.render();
    console.log('检测到数组变化,触发更新');
    return ret;
  }
});

在Chrome中console运行示例:

let arr = [];
arr.__proto__ = arrayob;
arr.push(1);

结果显示:

Vue2.X和Vue3.0数据响应原理变化的区别 

Vue3.0数据响应原理

Vue3.0数据响应原理

创建页面,实现延时2s修改对象的值。代码同上。

Proxy实现:

function vue() {
  this.$data = {
    a: 1
  };
  this.el = document.getElementById('app');
  this._html = "";
  this.observe(this.$data);
  this.render();
}

vue.prototype.observe = function (obj) {
  let self = this;

  this.$data = new Proxy(this.$data, {
    get: function (target, key) {
      return target[key];
    },
    set: function (target, key, newvalue) {
      target[key] = newvalue;
      self.render();
    }
  })
}

vue.prototype.render = function () {
  this._html = "I am " + this.$data.a;
  this.el.innerHTML = this._html;
}

在Chrome中console运行,结果页面显示: I am 444

为什么改用Proxy

  • defineProperty只能监听某个属性,不能对全对象监听
  • 可以省去for in循环提升效率
  • 可以监听数组,不用再去单独的对数组做特异性操作

Proxy还能做什么

校验类型

function createValidator(target, validator) {
  return new Proxy(target, {
    _validator: validator,
    set(target, key, value, proxy) {
      if(target.hasOwnProperty(key)) {
        let validator = this._validator[key];
        if(validator(value)) {
          return Reflect.set(target, key, value, proxy);
        } else {
          throw Error('type error');
        }
      }
    }
  })
}

let personValidator = {
  name(val) {
    return typeof val === 'string';
  },
  age(val) {
    return typeof val === 'number' && val > 18;
  }
}

class person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
    return createValidator(this, personValidator);
  }
}

在Chrome中console运行示例:

let tmp = new person('张三', 30);

结果显示:

Vue2.X和Vue3.0数据响应原理变化的区别

真正的私有变量

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 简练的几个函数
Aug 29 Javascript
jquery.fileEveryWhere.js 一个跨浏览器的file显示插件
Oct 24 Javascript
js将控件隐藏及display属性的使用介绍
Dec 30 Javascript
JavaScript制作的可折叠弹出式菜单示例
Apr 04 Javascript
BootStrap入门教程(二)之固定的内置样式
Sep 19 Javascript
jQuery中的on与bind绑定事件区别实例详解
Feb 28 Javascript
JS 中使用Promise 实现红绿灯实例代码(demo)
Oct 20 Javascript
vue父组件点击触发子组件事件的实例讲解
Feb 08 Javascript
微信小程序自定义多选事件的实现代码
May 17 Javascript
angular4+百分比进度显示插件用法示例
May 05 Javascript
JS实现的简单tab切换功能完整示例
Jun 20 Javascript
基于iview-admin实现动态路由的示例代码
Oct 02 Javascript
vue 实现v-for循环回来的数据动态绑定id
Nov 07 #Javascript
vue改变循环遍历后的数据实例
Nov 07 #Javascript
vue element-ui el-date-picker限制选择时间为当天之前的代码
Nov 07 #Javascript
vue v-for直接循环数字实例
Nov 07 #Javascript
jsonp格式前端发送和后台接受写法的代码详解
Nov 07 #Javascript
js实现数字从零慢慢增加到指定数字示例
Nov 07 #Javascript
详解Angular cli配置过程记录
Nov 07 #Javascript
You might like
php中通过虚代理实现延迟加载的实现代码
2011/06/10 PHP
php文本转图片自动换行的方法
2013/03/13 PHP
thinkphp中memcache的用法实例
2014/11/29 PHP
PHP查询快递信息的方法
2015/03/07 PHP
php通过asort()给关联数组按照值排序的方法
2015/03/18 PHP
WordPress中给媒体文件添加分类和标签的PHP功能实现
2015/12/31 PHP
php实现中文转数字
2016/02/18 PHP
PHP多线程模拟实现秒杀抢单
2018/02/07 PHP
PHP getName()函数讲解
2019/02/03 PHP
PHP单元测试配置与使用方法详解
2019/12/27 PHP
jQuery使用手册之 事件处理
2007/03/24 Javascript
JS解密入门 最终变量劫持
2008/06/25 Javascript
拖动布局之保存布局页面cookies篇
2010/10/29 Javascript
js传参数受特殊字符影响错误的解决方法
2013/10/21 Javascript
asp.net+js实现金额格式化
2015/02/27 Javascript
JQuery操作textarea,input,select,checkbox方法
2015/09/02 Javascript
跟我学习javascript的arguments对象
2015/11/16 Javascript
分享js粘帖屏幕截图到web页面插件screenshot-paste
2020/08/21 Javascript
js获取客户端操作系统类型的方法【测试可用】
2016/05/27 Javascript
基于JavaScript实现微信抢红包功能
2017/07/20 Javascript
js将键值对字符串转为json字符串的方法
2018/03/30 Javascript
Vue 实现手动刷新组件的方法
2019/02/19 Javascript
详解微信小程序回到顶部的两种方式
2019/05/09 Javascript
layui 数据表格 根据值(1=业务,2=机构)显示中文名称示例
2019/10/26 Javascript
Element InfiniteScroll无限滚动的具体使用方法
2020/07/27 Javascript
[03:55]2016国际邀请赛中国区预选赛首日TOP10精彩集锦
2016/06/27 DOTA
Python使用新浪微博API发送微博的例子
2014/04/10 Python
Python入门教程之if语句的用法
2015/05/14 Python
python+pillow绘制矩阵盖尔圆简单实例
2018/01/16 Python
在Python dataframe中出生日期转化为年龄的实现方法
2018/10/20 Python
美国牛仔品牌:True Religion
2018/11/16 全球购物
师范生自荐信范文
2013/10/06 职场文书
学校先进集体事迹材料
2014/05/31 职场文书
旅游局领导班子“四风”问题对照检查材料思想汇报
2014/09/29 职场文书
MySQL系列之一 MariaDB-server安装
2021/07/02 MySQL
使用 Apache Dubbo 实现远程通信(微服务架构)
2022/02/12 Servers