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 相关文章推荐
用dtree实现树形菜单 dtree使用说明
Oct 17 Javascript
jquery.cookie.js实现用户登录保存密码功能的方法
Apr 15 Javascript
JavaScript_ECMA5数组新特性详解
Jun 12 Javascript
实例讲解JavaScript中call、apply、bind方法的异同
Sep 13 Javascript
JS实战篇之收缩菜单表单布局
Dec 10 Javascript
vue-router相关基础知识及工作原理
Mar 16 Javascript
jQuery each和js forEach用法比较
Feb 27 jQuery
JavaScript迭代器的含义及用法
Jun 21 Javascript
bootstrap table插件动态加载表头
Jul 19 Javascript
jQuery实现回到顶部效果
Oct 19 jQuery
在elementui中Notification组件添加点击事件实例
Nov 11 Javascript
Vue中Object.assign清空数据报错的解决方案
Mar 03 Vue.js
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在线生成二维码代码(google api)
2013/06/03 PHP
PHP 爬取网页的主要方法
2018/07/13 PHP
thinkphp5使html5实现动态跳转的例子
2019/10/16 PHP
JQuery 无废话系列教程(一) jquery入门 [推荐]
2009/06/23 Javascript
jquery 操作单选框,复选框,下拉列表实现代码
2009/10/27 Javascript
本地对象Array的原型扩展实现代码
2010/12/04 Javascript
js中关于String对象的replace使用详解
2011/05/24 Javascript
浅谈angularJS 作用域
2015/07/05 Javascript
jQuery Mobile中的button按钮组件基础使用教程
2016/05/23 Javascript
全面解析标签页的切换方式
2016/08/21 Javascript
老生常谈javascript变量的命名规范和注释
2016/09/29 Javascript
简单实现Bootstrap标签页
2020/08/09 Javascript
JS HTML图片显示Canvas 压缩功能
2017/07/21 Javascript
node.js文件上传重命名以及移动位置的示例代码
2018/01/19 Javascript
又拍云 Node.js 实现文件上传、删除功能
2018/10/28 Javascript
vue中利用simplemde实现markdown编辑器(增加图片上传功能)
2019/04/29 Javascript
微信小程序云开发之模拟后台增删改查
2019/05/16 Javascript
webpack中如何加载静态文件的方法步骤
2019/05/18 Javascript
es5 类与es6中class的区别小结
2020/11/09 Javascript
[01:01:31]2018DOTA2亚洲邀请赛3月29日小组赛B组 Mineski VS paiN
2018/03/30 DOTA
[02:16]完美世界DOTA2联赛PWL S3 集锦第三期
2020/12/21 DOTA
在Python上基于Markov链生成伪随机文本的教程
2015/04/17 Python
python框架django基础指南
2016/09/08 Python
python 列表,数组,矩阵两两转换tolist()的实例
2018/04/04 Python
Django+uni-app实现数据通信中的请求跨域的示例代码
2019/10/12 Python
用Python开发app后端有优势吗
2020/06/29 Python
Expedia印度尼西亚站:预订酒店、廉价航班和度假套餐
2018/01/31 全球购物
Carter’s OshKosh加拿大:购买婴幼儿服装和童装
2018/11/27 全球购物
EMPHASIS艾斐诗官网:周生生旗下原创精品珠宝品牌
2020/12/17 全球购物
技能比赛获奖感言
2014/02/14 职场文书
公司财务会计主管应聘求职信
2014/09/26 职场文书
中学生社区服务活动报告
2015/02/05 职场文书
物业公司管理制度
2015/08/05 职场文书
MySQL完整性约束的定义与实例教程
2021/05/30 MySQL
十大最强妖精系宝可梦,哲尔尼亚斯实力最强,第五被称为大力士
2022/03/18 日漫
SQL Server中使用表变量和临时表
2022/05/20 SQL Server