We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
理解Vue的observer机制,实现一个简单数据观测。
难点解析:
简单的赋值操作监听:
var data = { x: 100 } function callback (val) { console.log('val', val) } Object.defineProperty(data, 'x', { get: function () { return data['x'] }, set: function (newVal) { callback(newVal) } }) data.x = 200
通过Object.defineProperty方法我们能做到非常简单的赋值监听,结合以上的难点解析,慢慢深入实现一个数据监听。
源码:
/* * Object 原型 */ const OP = Object.prototype; /* * 需要重写的数组方法 OAR 是 overrideArrayMethod 的缩写 */ const OAM = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse']; export class Jsonob{ constructor(obj, callback){ if(OP.toString.call(obj) !== '[object Object]'){ console.error('This parameter must be an object:' + obj); } this.$callback = callback; this.observe(obj); } /** * 监测数据对象 * @param {Object} obj [要监测的数据对象] * @param {Array} path [属性路径] */ observe(obj, path){ if(OP.toString.call(obj) === '[object Array]'){ this.overrideArrayProto(obj, path); } Object.keys(obj).forEach(function(key, index, keyArray){ var oldVal = obj[key]; var pathArray = path && path.slice(0); if(pathArray){ pathArray.push(key); }else{ pathArray = [key]; } Object.defineProperty(obj, key, { get: function(){ return oldVal; }, set: (function(newVal){ if(oldVal !== newVal){ if(OP.toString.call(newVal) === '[object Object]' || OP.toString.call(newVal) === '[object Array]'){ this.observe(newVal, pathArray); } this.$callback(newVal, oldVal, pathArray); oldVal = newVal; } }).bind(this) }); if(OP.toString.call(obj[key]) === '[object Object]' || OP.toString.call(obj[key]) === '[object Array]'){ this.observe(obj[key], pathArray); } }, this); } /** * 重写数组的方法 * @param {Array} array [数组字段] * @param {Array} path [属性路径] */ overrideArrayProto(array, path){ var originalProto = Array.prototype, overrideProto = Object.create(Array.prototype), self = this, result; OAM.forEach(function(method, index, array){ var oldArray = []; Object.defineProperty(overrideProto, method, { value: function(){ oldArray = this.slice(0); var arg = [].slice.apply(arguments); result = originalProto[method].apply(this, arg); self.observe(this, path); self.$callback(this, oldArray, path); return result; }, writable: true, enumerable: false, configurable: true }); }, this); array.__proto__ = overrideProto; } }
<html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <script type="module"> import { Jsonob } from './jsonob.js' var callback = function(newVal, oldVal, path){ console.log('新值:' + newVal + '----' + '旧值:' + oldVal + '----路径:' + path); }; var data = { a: 200, level1: { b: 'str', c: [{w: 90}, 2, 3], level2: { d: 90 } } } var j = new Jsonob(data, callback); data.level1.c.push(4); data.level1.c[0].w = 100; data.level1.b = 'sss'; data.level1.level2.d = 'msn'; </script> </body> </html>
参考:JavaScript实现MVVM之我就是想监测一个普通对象的变化
The text was updated successfully, but these errors were encountered:
No branches or pull requests
理解Vue的observer机制,实现一个简单数据观测。
难点解析:
简单的赋值操作监听:
通过Object.defineProperty方法我们能做到非常简单的赋值监听,结合以上的难点解析,慢慢深入实现一个数据监听。
源码:
参考:JavaScript实现MVVM之我就是想监测一个普通对象的变化
The text was updated successfully, but these errors were encountered: