当嵌套组件更新时,Svelte存储库不会触发onchange

nvi*_*oli 5 javascript svelte

假设我要创建一个带有苗条的多色选择器,也许让用户选择前景色和背景色。我的数据模型如下所示:

{
  foreground: {
    r: 100,g:100,b:100
  },
  background: {
    r: 200,g:200,b:200
  }
};
Run Code Online (Sandbox Code Playgroud)

所以我的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;
Run Code Online (Sandbox Code Playgroud)

然后,我可以构建一个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}}
Run Code Online (Sandbox Code Playgroud)

App.html的很简单:

foreground:
<RGBSelector bind:data=$foreground/>

background:
<RGBSelector bind:data=$background/>

<script>
  import RGBSelector from './RGBSelector.html';

  export default {
    components: {
      RGBSelector
    }
  };
</script>
Run Code Online (Sandbox Code Playgroud)

这似乎很有效。范围输入中的双向绑定正在工作(标签更新),甚至商店也正在更新(通过store._state在控制台中检查来验证)。因此,我相信中的bind关键字会将RGBSelector更改传递到在中声明的位置App,从而将bind其发送到商店。

麻烦的是,store.onchange处理程序未触发。谁能看到我在做什么错?

完整示例:https//glitch.com/edit/#!/ nonstop-hourglass

Ric*_*ris 3

这是 Svelte 中的错误,而不是您的应用程序!事实证明,组件绑定不能很好地与store\xe2\x80\x94 配合使用,它bind:data=$foreground只是$foreground<App>组件中更新而不是更新foreground在商店中更新。

\n\n

在这里跟踪问题: https ://github.com/sveltejs/svelte/issues/1100

\n\n

遗憾的是,在我们修复此问题之前,没有很好的解决方法\xe2\x80\x94,您需要执行以下操作:

\n\n
foreground: <RGBSelector bind:data=foreground/>\nbackground: <RGBSelector bind:data=background/>\ntext: <Textinput bind:value=text/>\n\n<script>\n  import RGBSelector from \'./RGBSelector.html\';\n  import Textinput from \'./Textinput.html\';\n\n  export default {\n    components: {\n      RGBSelector, Textinput\n    },\n\n    oncreate() {\n      this.observe(\'foreground\', foreground => {\n        this.store.set({ foreground });\n      });\n\n      this.observe(\'background\', background => {\n        this.store.set({ background });\n      });\n\n      this.observe(\'text\', text => {\n        this.store.set({ text });\n      });\n    }\n  };\n</script>\n
Run Code Online (Sandbox Code Playgroud)\n\n

在你的 JS 文件中,这样:

\n\n
var app = new App({\n  target: document.body,\n  data: defaultData,\n  store\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果更改可以双向进行,您还需要观察存储属性,注意防止无限更新循环:

\n\n
// inside `oncreate` \xe2\x80\x94 would also need to do this\n// for `background` and `text`\nlet foregroundUpdating = false;\n\nthis.observe(\'foreground\', foreground => {\n  if (foregroundUpdating) return;\n  foregroundUpdating = true;\n  this.store.set({ foreground });\n  foregroundUpdating = false;\n});\n\nthis.store.observe(\'foreground\', foreground => {\n  if (foregroundUpdating) return;\n  foregroundUpdating = true;\n  this.set({ foreground });\n  foregroundUpdating = false;\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

重新创建这样的绑定功能显然有点麻烦,因此我们将尝试尽快修复此错误。

\n