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 getElementsByName()的用法说明
Jul 31 Javascript
用Javascript 和 CSS 实现脚注(Footnote)效果
Sep 09 Javascript
改变隐藏的input中value值的方法
Mar 19 Javascript
js调试系列 控制台命令行API使用方法
Jun 18 Javascript
JavaScript获得当前网页来源页面(即上一页)的方法
Apr 03 Javascript
js正则匹配出所有图片及图片地址src的方法
Jun 08 Javascript
js仿京东轮播效果 选项卡套选项卡使用
Jan 12 Javascript
使用requirejs模块化开发多页面一个入口js的使用方式
Jun 14 Javascript
layui多图上传实现删除功能的例子
Sep 23 Javascript
js实现自动播放匀速轮播图
Feb 06 Javascript
Vue3为什么这么快
Sep 23 Javascript
vue调用微信JSDK 扫一扫,相册等需要注意的事项
Jan 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连接SQLServer2005的实现方法(附ntwdblib.dll下载)
2012/07/02 PHP
自己写的php curl库实现整站克隆功能
2015/02/12 PHP
php对二维数组进行相关操作(排序、转换、去空白等)
2015/11/04 PHP
PHP简单读取xml文件的方法示例
2017/04/20 PHP
Javascript 调试利器 Firebug使用详解六
2009/07/05 Javascript
javascript 面向对象继承
2009/11/26 Javascript
clipboard.js无需Flash无需依赖任何JS库实现文本复制与剪切
2015/10/10 Javascript
详解AngularJS 模态对话框
2016/04/07 Javascript
Chrome不支持showModalDialog模态对话框和无法返回returnValue问题的解决方法
2016/10/30 Javascript
JavaScript实现格式化字符串函数String.format
2016/12/16 Javascript
使用BootStrap实现标签切换原理解析
2017/03/14 Javascript
vue 2.0路由之路由嵌套示例详解
2017/05/08 Javascript
vue.js的手脚架vue-cli项目搭建的步骤
2017/08/30 Javascript
JS组件系列之Gojs组件 前端图形化插件之利器
2017/11/29 Javascript
ionic3实战教程之随机布局瀑布流的实现方法
2017/12/28 Javascript
浅谈mvvm-simple双向绑定简单实现
2018/04/18 Javascript
JS实现倒计时图文效果
2018/11/17 Javascript
vue增加强缓存和版本号的实现方法
2019/05/01 Javascript
通过实例了解js函数中参数的传递
2019/06/15 Javascript
nestjs返回给前端数据格式的封装实现
2021/02/22 Javascript
python 创建弹出式菜单的实现代码
2017/07/11 Python
python实现朴素贝叶斯分类器
2018/03/28 Python
pyqt5实现俄罗斯方块游戏
2019/01/11 Python
python 多个参数不为空校验方法
2019/02/14 Python
用Python批量把文件复制到另一个文件夹的实现方法
2019/08/16 Python
python调用c++返回带成员指针的类指针实例
2019/12/12 Python
如何卸载python插件
2020/07/08 Python
利用CSS3实现进度条的两种姿势详解
2017/03/21 HTML / CSS
Julep官网:美容产品和指甲油
2017/02/25 全球购物
Superdry瑞典官网:英国日本街头风品牌
2017/05/17 全球购物
澳大利亚在线高跟鞋商店:Shoe Me
2019/11/19 全球购物
MIS软件工程师的面试题
2016/04/22 面试题
清华大学自主招生自荐信
2014/01/29 职场文书
会计与出纳自荐书范文
2014/03/16 职场文书
计划生育个人总结
2015/03/02 职场文书
MySQL数据库优化之通过索引解决SQL性能问题
2022/04/10 MySQL