6

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

{
  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处理程序没有开火。谁能看到我做错了什么?

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

4

1 回答 1

3

这是 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;
});

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

于 2018-01-12T13:08:39.530 回答