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 相关文章推荐
js 编写规范
Mar 03 Javascript
javascript中字符串的定义示例代码
Dec 19 Javascript
基于jQuey实现鼠标滑过变色(整行变色)
Dec 07 Javascript
详解js中常规日期格式处理、月历渲染和倒计时函数
Dec 28 Javascript
微信小程序开发之animation循环动画实现的让云朵飘效果
Jul 14 Javascript
Javascript实现秒表倒计时功能
Nov 17 Javascript
小程序异步问题之多个网络请求依次执行并依次收集请求结果
May 05 Javascript
Vue中常用rules校验规则(实例代码)
Nov 14 Javascript
vue多个元素的样式选择器问题
Nov 29 Javascript
JavaScript实现轮播图片完整代码
Mar 07 Javascript
JS Html转义和反转义(html编码和解码)的实现与使用方法总结
Mar 10 Javascript
vue自动添加浏览器兼容前后缀操作
Aug 13 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
桌面中心(四)数据显示
2006/10/09 PHP
PHP中函数内引用全局变量的方法
2008/10/20 PHP
判断Keep-Alive模式的HTTP请求的结束的实现代码
2011/08/06 PHP
thinkphp5框架结合mysql实现微信登录和自定义分享链接与图文功能示例
2019/08/13 PHP
js 内存释放问题
2010/04/25 Javascript
js输出列表实现代码
2010/09/12 Javascript
用Jquery.load载入页面实现局部刷新
2014/01/22 Javascript
12行javascript代码绘制一个八卦图
2015/04/02 Javascript
javascript省市级联功能实现方法实例详解
2015/10/20 Javascript
JS实现的自定义网页拖动类
2015/11/06 Javascript
使用Jasmine和Karma对AngularJS页面程序进行测试
2016/03/05 Javascript
AngularJs篇:使用AngularJs打造一个简易权限系统的实现代码
2016/12/26 Javascript
深入理解Vuex 模块化(module)
2017/09/26 Javascript
对node.js中render和send的用法详解
2018/05/14 Javascript
js中split()方法得到的数组长度问题
2018/07/19 Javascript
Layui 设置select下拉框自动选中某项的方法
2018/08/14 Javascript
vue 音乐App QQ音乐搜索列表最新接口跨域设置方法
2018/09/25 Javascript
JS返回页面时自动回滚到历史浏览位置
2018/09/26 Javascript
小程序云开发如何实现图片上传及发表文字
2019/05/17 Javascript
微信小程序静默登录的实现代码
2020/01/08 Javascript
vue props default Array或是Object的正确写法说明
2020/07/30 Javascript
vue使用swiper实现左右滑动切换图片
2020/10/16 Javascript
python实现word 2007文档转换为pdf文件
2018/03/15 Python
配置 Pycharm 默认 Test runner 的图文教程
2018/11/30 Python
在Mac中PyCharm配置python Anaconda环境过程图解
2020/03/11 Python
Python爬虫实现vip电影下载的示例代码
2020/04/20 Python
将pycharm配置为matlab或者spyder的用法说明
2020/06/08 Python
python温度转换华氏温度实现代码
2020/12/06 Python
HTML5 3D书本翻页动画的实现示例
2019/08/28 HTML / CSS
美国休闲服装品牌:Express
2016/09/24 全球购物
Darphin迪梵官网: 来自巴黎,植物和精油调制的护肤品牌
2016/10/11 全球购物
财务支持类个人的自我评价
2014/02/14 职场文书
师德先进个人材料
2014/12/20 职场文书
2015年小学重阳节活动总结
2015/07/29 职场文书
2015年学校消防安全工作总结
2015/10/14 职场文书
Win11跳过联网界面创建本地管理账户的3种方法
2022/04/20 数码科技