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 相关文章推荐
避免回车键导致的页面无意义刷新的解决方法
Apr 12 Javascript
javascript学习笔记(七) js函数介绍
Jun 19 Javascript
javascript实现原生ajax的几种方法介绍
Sep 21 Javascript
javascript在网页中实现读取剪贴板粘贴截图功能
Jun 07 Javascript
在Node.js中使用HTTP上传文件的方法
Jun 23 Javascript
详解 javascript中offsetleft属性的用法
Nov 11 Javascript
使用递归遍历对象获得value值的实现方法
Jun 14 Javascript
BootStrap框架中的data-[ ]自定义属性理解(推荐)
Feb 14 Javascript
angularjs ui-router中路由的二级嵌套
Mar 10 Javascript
vue项目中跳转到外部链接的实例讲解
Sep 20 Javascript
js的新生代垃圾回收知识点总结
Aug 22 Javascript
ES6中new Function()语法及应用实例分析
Feb 19 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
帅气的琦玉老师
2020/03/02 日漫
PHP中Session的概念
2006/10/09 PHP
php smarty模版引擎中变量操作符及使用方法
2009/12/11 PHP
《PHP编程最快明白》第八讲:php启发和小结
2010/11/01 PHP
ThinkPHP使用心得分享-ThinkPHP + Ajax 实现2级联动下拉菜单
2014/05/15 PHP
Destoon旺旺无法正常显示,点击提示“会员名不存在”的解决办法
2014/06/21 PHP
CI框架中site_url()和base_url()的区别
2015/01/07 PHP
PHP框架Laravel学习心得体会
2015/10/28 PHP
浅谈Laravel POST,PUT,PATCH 路由的区别
2019/10/15 PHP
用javascript动态调整iframe高度的方法
2007/03/06 Javascript
2007/12/23更新创意无限,简单实用(javascript log)
2007/12/24 Javascript
详细讲解JS节点知识
2010/01/31 Javascript
JQuery标签页效果实例详解
2015/12/24 Javascript
Jsonp 关键字详解及json和jsonp的区别,ajax和jsonp的区别
2015/12/30 Javascript
jQuery 检查某个元素在页面上是否存在实例代码
2016/10/27 Javascript
JS实现浏览器打印、打印预览示例
2017/02/28 Javascript
基于jQuery对象和DOM对象和字符串之间的转化实例
2017/08/08 jQuery
Vue渲染函数详解
2017/09/15 Javascript
详解如何在微信小程序开发中正确的使用vant ui组件
2018/09/13 Javascript
使用jquery-easyui的布局layout写后台管理页面的代码详解
2019/06/19 jQuery
js神秘的电报密码 哈弗曼编码实现
2019/09/10 Javascript
JS数组方法shift()、unshift()用法实例分析
2020/01/18 Javascript
Python编程之微信推送模板消息功能示例
2017/08/21 Python
对django xadmin自定义菜单的实例详解
2019/01/03 Python
Python操作excel的方法总结(xlrd、xlwt、openpyxl)
2019/09/02 Python
Python之Class&amp;Object用法详解
2019/12/25 Python
Python多线程threading join和守护线程setDeamon原理详解
2020/03/18 Python
如何学习Python time模块
2020/06/03 Python
应用外语系自荐信
2014/06/26 职场文书
返乡农民工证明
2015/06/24 职场文书
2016暑期政治学习心得体会
2016/01/23 职场文书
高二英语教学反思
2016/03/03 职场文书
纪念建国70周年演讲稿
2019/07/19 职场文书
javascript canvas实现雨滴效果
2021/06/09 Javascript
Oracle以逗号分隔的字符串拆分为多行数据实例详解
2021/07/16 Oracle
Apache Pulsar集群搭建部署详细过程
2022/02/12 Servers