在过去几年中,响应式已成为事实上的标准。所有主要框架都实现了一些响应式模型。其中最大的一个甚至被称为react。在本文中,我们将了解如何仅使用几行JavaScript编写简单的响应式UI 。
当谈论响应式 UI 时,我们通常指的是当数据发生变化时自动更新的界面。这种方法变得流行,因为它使开发更容易理解和维护。真相只有一个来源,我们只关心更新它,而不考虑实际的 UI 更新。
我们可以使用一个本机浏览器 api 来实现该响应式。这是代理对象。
Proxy 对象使您能够为另一个对象创建代理,该代理可以拦截并重新定义该对象的基本操作。
这意味着我们可以在设置或获取代理对象的属性时注入代码。这是一个简单的例子:
const target = {
name: "Foo"
};
const handler = {
get(target, prop, receiver) {
return "Proxied: " + target[prop];
},
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); // Proxied: Foo
该proxy常数几乎与我们原来的常数相同target。它也包含该name属性,但Foo它的值不是 ,而是Proxied: Foo。
连同get,我们还有一个set方法。因此,我们可以执行以下操作:
const target = {
name: "Foo"
};
const handler = {
get(target, prop, receiver) {
return "Proxied: " + target[prop];
},
set(obj, prop, value) {
obj[prop] = 'Bar';
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); // Proxied: Foo
proxy.name = 'A new name value';
console.log(proxy.name); // Proxied: Bar
请注意,即使我们在最后获得Proxied:Bar时将name的值设置为“新名称值”。这是因为setter获取控制权,并将Bar指定为一个值。稍后,我们返回前缀为Proxied:Bar,因为我们有一个自定义getter。
现在,让我们使用 setter 来制作响应式 UI。
我们大多数人现在使用的反应式模型也可以定义为单向数据流。
这是一个简单的想法,我们有状态,而我们的 UI 是它的函数。然后,每次用户交互都会导致状态更改,并且渲染会自动发生。如果我们要改变界面,我们不会去dom而是改变状态。这就是我们想要在这里实现的响应式。使用Proxy API,我们只需十行代码即可完成:
function createReactivity(initialState, onUpdate) {
const proxy = new Proxy(initialState, {
set(obj, prop, value) {
obj[prop] = value
onUpdate.call(proxy);
}
});
onUpdate.call(proxy);
return proxy;
}
它createReactivity接受我们的初始状态对象和一个回调函数,每当数据更新时就会触发该回调函数。
实际的例子是这样的:
<div id="container"></div>
<input autofocus />
<script>
function createReactivity(initialState, onUpdate) {
const proxy = new Proxy(initialState, {
set(obj, prop, value) {
obj[prop] = value
onUpdate.call(proxy);
}
});
onUpdate.call(proxy);
return proxy;
}
const state = createReactivity({ name: 'Krasimir' }, function () {
document.querySelector('#container').innerhtml = `
<h1>Hello, ${this.name}</h1>
`;
});
const input = document.querySelector('input');
input.addEventListener('input', e => state.name = e.target.value);
input.value = state.name;
</script>
每当我们更改输入字段的值时,我们都会更新name代理对象的属性。这会导致调用 setter 并触发回调onUpdate,从而将新的 HTML 应用于元素#container。
5 天前