假设我想在没有任何框架的情况下实现双向数据绑定。我知道可以通过Object.defineProperty()
或Proxy
等多种方法实现。但是,所有这些方法都需要在obj.a = 'new value'
之类的对象的属性上进行更改。是否可以直接观察变量的变化,这样我可以在其他地方调用name = 'new value'
时执行我自己的代码?
// A string variable
var name = 'some value';
function nameChanged(newValue) {
document.getElementById('name').value = newValue;
}
// magic goes here...
...
name = 'new value' // nameChanged() is automatically called.
答案 0 :(得分:1)
根据您所在的范围(我假设您只是在全球范围内),您可以使用Object.defineProperty
并将目标对象设置为window
。
Object.defineProperty( window, 'name', {
get() {
return this._name;
},
set(value) {
if (value === this.name) {
// didn't change so return
return;
}
var oldValue = this.name;
this._name = value;
console.log( `Changed 'name' from ${oldValue} to ${value}` );
}
});
name = 'test';
name = 'test2';
name = 'test2';
console.log(name);
如果您不在全球范围内,那么这将无效。说实话,我不明白为什么你会强迫它在原始变量上。
如果你想制作自己的观察者版本,你当然可以自己实现像
这样的东西
const createObjectProperty = (context, scope, handleChange) => (property) => {
Object.defineProperty( context, property, {
get() {
return scope[property];
},
set( value ) {
let old = context[property];
if (old === value) {
return;
}
scope[property] = value;
handleChange( property, value, old );
}
});
};
class Bound {
constructor( callback, ...props) {
this.propertyCreator = createObjectProperty(this, {}, this.handlePropertyChanged.bind( this ) );
if ( callback && !callback.apply ) {
// probably property
props = [ callback, ...props ];
} else {
this.callback = callback;
}
props && props.forEach( this.addProperty.bind( this ) );
}
addProperty( property ) {
this.propertyCreator( property );
}
handlePropertyChanged( property, newValue, oldValue ) {
let { callback } = this;
callback && callback.apply && callback.apply( this, [property, newValue, oldValue] );
}
}
var b = new Bound( (property, newValue, oldValue) => {
console.log( `${property} changed from ${oldValue} to ${newValue}` );
}, 'name', 'lastName' );
b.name = 'test';
b.lastName = 'another test';
console.log( b.name );
console.log( b.lastName );
var b2 = new Bound('test');
b2.test = 'hey joe';
b2.callback = () => { console.log('test changed') };
b2.test = 'hey marie';
console.log( b2.test );
b2.addProperty('name');
b2.name = 'test';
答案 1 :(得分:0)
没有。 Javascript不允许您挂钩该操作。例如,可以在python
中使用类似__add__
的钩子。但是在python中,你需要构建自己类型的对象(类),然后你就可以决定它发生了什么。
例如,创建一个类Person
,然后创建所需的方法,您可以根据自己的意愿进行操作。
class Person {
constructor(name) {
this.name = name;
}
setName(name) {
//Whatever it is you wanna do
this.name = name;
}
}
答案 2 :(得分:0)
您可以将变量定义为函数,并在调用函数时执行任务
const NAME = 123;
const _name = (value = NAME) => {
if (value !== NAME) {
// do stuff
};
return value
};