假设我想用 svelte 创建一个多色选择器,也许让用户选择前景色和背景色。我的数据模型如下所示:
{
foreground: {
r: 100,g:100,b:100
},
background: {
r: 200,g:200,b:200
}
};
所以我的 app.js 是
import AppUI from './App.html';
import { Store } from 'svelte/store.js';
const defaultData = {
foreground: {
r: 100,g:100,b:100
},
background: {
r: 200,g:200,b:200
}
};
const store = new Store(defaultData);
window.store = store; // useful for debugging!
store.onchange(() => console.log('something changed'));
var app = new AppUI({
target: document.querySelector( '#main' ),
store
});
export default app;
然后我可以构建一个 RGBSelector
组件来重用:
<input type="range" min=0 max=255 step=1 bind:value=data.r/>{{data.r}}
<input type="range" min=0 max=255 step=1 bind:value=data.g/>{{data.g}}
<input type="range" min=0 max=255 step=1 bind:value=data.b/>{{data.b}}
我的 App.html
非常简单:
foreground:
<RGBSelector bind:data=$foreground/>
background:
<RGBSelector bind:data=$background/>
<script>
import RGBSelector from './RGBSelector.html';
export default {
components: {
RGBSelector
}
};
</script>
这似乎大部分都有效。范围输入中的双向绑定(bind)正在工作(标签更新),商店甚至正在更新(通过检查控制台中的 store._state
进行验证)。所以我相信 RGBSelector
中的 bind
关键字将更改传递到它们在 App
中声明的位置,而 App
又是 绑定(bind)
它们到商店。
问题是,store.onchange
处理程序没有触发。谁能看出我做错了什么?
最佳答案
这是 Svelte 中的错误,而不是您的应用程序!事实证明组件绑定(bind)不能很好地与 store
配合使用— bind:data=$foreground
正在更新 $foreground
在你的<App>
组件而不是更新 foreground
在您的商店中。
在此处跟踪问题:https://github.com/sveltejs/svelte/issues/1100
遗憾的是,没有很好的解决方法 — 在我们解决此问题之前,您需要执行以下操作:
foreground: <RGBSelector bind:data=foreground/>
background: <RGBSelector bind:data=background/>
text: <Textinput bind:value=text/>
<script>
import RGBSelector from './RGBSelector.html';
import Textinput from './Textinput.html';
export default {
components: {
RGBSelector, Textinput
},
oncreate() {
this.observe('foreground', foreground => {
this.store.set({ foreground });
});
this.observe('background', background => {
this.store.set({ background });
});
this.observe('text', text => {
this.store.set({ text });
});
}
};
</script>
在你的 JS 文件中,这个:
var app = new App({
target: document.body,
data: defaultData,
store
});
如果更改可以双向进行,您还需要观察存储属性,注意防止无限更新循环:
// inside `oncreate` — would also need to do this
// for `background` and `text`
let foregroundUpdating = false;
this.observe('foreground', foreground => {
if (foregroundUpdating) return;
foregroundUpdating = true;
this.store.set({ foreground });
foregroundUpdating = false;
});
this.store.observe('foreground', foreground => {
if (foregroundUpdating) return;
foregroundUpdating = true;
this.set({ foreground });
foregroundUpdating = false;
});
像这样重新创建绑定(bind)的功能显然有点麻烦,所以我们会尽快修复这个错误。
关于javascript - 嵌套组件更新时,Svelte 商店不会触发 onchange,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48177495/