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

时间:2018-01-09 22:22:19

标签: javascript 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>

这似乎很有效。范围输入中的双向绑定正在工作(标签更新),甚至更新存储(通过检查控制台中的store._state进行验证)。因此,我认为bind中的RGBSelector个关键字正在将更改传递到他们在App中声明的位置,而bind依次为store.onchange商店。

麻烦的是,import pyglet import time import random window = pyglet.window.Window() while True: images = ["Image 1.png", "Image 2.png", "Image 3.png"] choice = images[random.randint(0,2)] rawImage = pyglet.resource.image(choice) sprite = pyglet.sprite.Sprite(rawImage) @window.event def on_draw(): window.clear() sprite.draw() time.sleep(2) pyglet.app.run() 处理程序没有触发。谁能看到我做错了什么?

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

1 个答案:

答案 0 :(得分:2)

这是Svelte中的错误,而不是您的应用!事实证明,组件绑定与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;
});

重新创建像这样的绑定功能显然有点麻烦,所以我们会尽快修复这个错误。