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作用域与作用域链深入解析
Dec 06 Javascript
七个很有意思的PHP函数
May 12 Javascript
Jquery选择器中使用变量实现动态选择例子
Jul 25 Javascript
通过jquery 获取URL参数并进行转码
Aug 18 Javascript
jQuery制作仿Mac Lion OS滚动条效果
Feb 10 Javascript
jQuery消息提示框插件Tipso
May 04 Javascript
javascript引用类型之时间Date和数组Array
Aug 27 Javascript
JavaScript中字面量与函数的基本使用知识
Oct 20 Javascript
在Vue项目中引入腾讯验证码服务的教程
Apr 03 Javascript
element-ui中dialog弹窗关闭按钮失效的解决
Sep 22 Javascript
解决ant design vue 表格a-table二次封装,slots渲染的问题
Oct 28 Javascript
使用Vant完成Dialog弹框案例
Nov 11 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注入实例
2006/10/09 PHP
PHP与javascript的两种交互方式
2006/10/09 PHP
php生成图片验证码的方法
2016/04/15 PHP
PHP实现的登录,注册及密码修改功能分析
2016/11/25 PHP
php实现将二维关联数组转换成字符串的方法详解
2017/07/31 PHP
PHP CURL与java http使用方法详解
2018/01/26 PHP
use jscript Create a SQL Server database
2007/06/16 Javascript
jQuery学习7 操作JavaScript对象和集合的函数
2010/02/07 Javascript
js 点击按钮弹出另一页,选择值后,返回到当前页
2010/05/26 Javascript
jQuery 操作option的实现代码
2011/03/03 Javascript
javascript按位非运算符的使用方法
2013/11/14 Javascript
javascript编写实用的省市选择器
2015/02/12 Javascript
Node.js实用代码段之正确拼接Buffer
2016/03/17 Javascript
基于jQuery实现音乐播放试听列表
2016/04/14 Javascript
JavaScript实现简单的四则运算计算器完整实例
2017/04/28 Javascript
微信小程序开发之toast提示插件使用示例
2017/06/08 Javascript
初学者AngularJS的环境搭建过程
2017/10/27 Javascript
判断文字超过2行添加展开按钮,未超过则不显示,溢出部分显示省略号
2019/04/28 Javascript
使用vue-router在Vue页面之间传递数据的方法
2019/07/15 Javascript
[02:34]DOTA2亚洲邀请赛 BG战队出场宣传片
2015/03/09 DOTA
[01:10:48]完美世界DOTA2联赛PWL S2 GXR vs PXG 第一场 11.18
2020/11/18 DOTA
用python实现批量重命名文件的代码
2012/05/25 Python
HTML中使用python屏蔽一些基本功能的方法
2017/07/07 Python
Python去除字符串前后空格的几种方法
2019/03/04 Python
Python3 tkinter 实现文件读取及保存功能
2019/09/12 Python
python pymysql链接数据库查询结果转为Dataframe实例
2020/06/05 Python
Python select及selectors模块概念用法详解
2020/06/22 Python
如何用用Python将地址标记在地图上
2021/02/07 Python
Canvas 文字碰撞检测并抽稀的方法
2019/05/27 HTML / CSS
美的官方商城:Midea
2016/09/14 全球购物
2014年迎新年活动方案
2014/02/19 职场文书
护理中职生求职信范文
2014/02/24 职场文书
创建青年文明号材料
2014/05/09 职场文书
卖车协议书范本4篇
2014/10/01 职场文书
政风行风评议工作总结
2014/10/21 职场文书
SQL Server Agent 服务无法启动
2022/04/20 SQL Server