检查JavaScript对象是否已更改的设计模式
我从服务器上得到一个对象列表检查JavaScript对象是否已更改的设计模式,javascript,design-patterns,Javascript,Design Patterns,我从服务器上得到一个对象列表 [{name:'test01', age:10},{name:'test02', age:20},{name:'test03', age:30}] 我将它们加载到html控件中供用户编辑。 然后有一个按钮将整个列表批量保存回数据库 我不想发送整个列表,只想发送已更改对象的子集 它可以是数组中任意数量的项。我想做一些类似于Angular之类的框架的事情,在没有对对象属性进行任何更改的情况下标记对象属性,如“pristine”。然后,使用该标志仅向服务器发布非“原始”
[{name:'test01', age:10},{name:'test02', age:20},{name:'test03', age:30}]
我将它们加载到html控件中供用户编辑。
然后有一个按钮将整个列表批量保存回数据库
我不想发送整个列表,只想发送已更改对象的子集
它可以是数组中任意数量的项。我想做一些类似于Angular之类的框架的事情,在没有对对象属性进行任何更改的情况下标记对象属性,如“pristine”。然后,使用该标志仅向服务器发布非“原始”的项,即已修改的项。无需对原型属性产生兴趣,只要在表单控件元素检测到更改时将其存储在另一个数组中即可 大致如下:
var modified = [];
data.forEach(function(item){
var domNode = // whatever you use to match data to form control element
domNode.addEventListener('input',function(){
if(modified.indexOf(item) === -1){
modified.push(item);
}
});
});
然后在需要保存时将
修改后的数组发送到服务器下面有一个函数,当提供旧的对象数组和新的对象数组时,该函数将返回已更改的对象数组:
getChanges=function(oldArray,newArray){
风险值变化,i,项目,j,len;
if(JSON.stringify(oldArray)==JSON.stringify(newArray)){
返回false;
}
变化=[];
对于(i=j=0,len=newArray.length;j
例如:
var older=[{name:'test01',age:10},{name:'test02',age:20},{name:'test03',age:30}]
var newer=[{name:'test01',age:10},{name:'test02',age:20},{name:'test03',age:20}]
getChanges(较旧、较新)
(注意test03的年龄现在是20岁)将返回
[{姓名:'test03',年龄:20}]
您只需在客户端导出编辑值的完整列表,将其与旧列表进行比较,然后将更改列表发送到服务器
希望这有帮助 以下是一些想法
使用框架。你说的是有棱角的
使用,尽管Internet Explorer不支持它
与其使用经典属性,不如使用的set/get实现某种更改跟踪
使用getter/setting函数来存储数据而不是属性:getName()
和setName()
。尽管这是defineProperty
现在所做的事情的老方法
每当您将数据绑定到表单元素时,请设置一个特殊属性,指示该属性是否已更改。类似于\u\u的内容发生了变化
。如果对象上的任何属性发生更改,则设置为true
传统的暴力方式:保留来自服务器的原始数据列表,将其深度复制到另一个列表中,将表单控件绑定到新列表中,然后当用户单击“提交”时,将原始列表中的对象与新列表中的对象进行比较,同时将更改的对象取出。可能是最简单的,但不一定是最干净的
对#6的不同理解:为每个始终返回对象原始版本的对象附加一个特殊属性:
var myData=[{name:“Larry”,年龄:47}];
var dataWithCopyOfSelf=myData.map(函数(数据){
赋值({},数据,{original:data});
});
//现在使用copyofself将表单绑定到数据。
为什么不使用Ember.js可观察属性?您可以使用Ember.observer函数获取和设置数据中的更改
Ember.Object.extend({
valueObserver: Ember.observer('value', function(sender, key, value, rev) {
// Executes whenever the "value" property changes
// See the addObserver method for more information about the callback arguments
})
});
实际上,Ember.object为您执行了很多繁重的操作
定义对象后,添加一个观察者,如下所示:
object.addObserver('propertyKey', targetObject, targetAction)
我的想法是对对象键进行排序,并将对象转换为字符串进行比较:
// use this function to sort keys, and save key=>value in an array
function objectSerilize(obj) {
let keys = Object.keys(obj)
let results = []
keys.sort((a, b) => a > b ? -1 : a < b ? 1 : 0)
keys.forEach(key => {
let value = obj[key]
if (typeof value === 'object') {
value = objectSerilize(value)
}
results.push({
key,
value,
})
})
return results
}
// use this function to compare
function compareObject(a, b) {
let aStr = JSON.stringify(objectSerilize(a))
let bStr = JSON.stringify(objectSerilize(b))
return aStr === bStr
}
//使用此函数对键进行排序,并将key=>值保存到数组中
函数对象序列化(obj){
让keys=Object.keys(obj)
让结果=[]
关键字排序((a,b)=>a>b?-1:a{
let value=obj[key]
如果(值的类型==='object'){
值=对象序列化(值)
}
结果:推({
钥匙
价值
})
})
返回结果
}
//使用此函数进行比较
函数比较对象(a,b){
让ast=JSON.stringify(objectserialize(a))
让bStr=JSON.stringify(objectserialize(b))
返回aStr==bStr
}
这就是我的想法。这将是最干净的,我认为当添加、删除或修改属性时,对象会发出一个事件。
一个简单的实现可能涉及一个带有对象键的数组;每当setter或heck构造函数返回此值时,它首先调用一个返回承诺的静态函数;解析:映射数组中已更改的值:添加的内容、删除的内容或两者都不添加。所以你可以得到(“改变”)等等;返回一个数组。
类似地,每个setter都可以发出一个带有初始值和新值参数的事件。
假设使用了类,您可以很容易地在父泛型类中拥有一个静态方法,该方法可以通过其构造函数调用,因此实际上您可以通过将对象传递给自身或通过super(checkMeProperty)传递给父类来简化大部分过程。对于ES6,我们可以使用
要完成此任务:截取对象写入,并将其标记为脏。
代理允许创建一个处理程序对象,该对象可以捕获、操纵并转发对原始目标对象的更改,基本上允许重新配置其行为。
我们将采用的陷阱来拦截对象写入操作是
此时,我们可以添加一个不可枚举的属性,例如:\u isDirty
,用于将对象标记为已修改的脏对象
当使用陷阱时(在我们的例子中,处理程序的set()
),不会对Obj应用或反映任何更改