javascript - 嵌套组件更新时,Svelte 商店不会触发 onchange

标签 javascript svelte

假设我想用 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 处理程序没有触发。谁能看出我做错了什么?

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

最佳答案

这是 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/

相关文章:

javascript - 为什么这个构造函数不起作用? (在 Ajax 的成功中)

svelte - 在 Svelte 中使用 postcss-normalize

html - 如何在 Svelte 中有条件地禁用字段?

svelte - 如何在开发模式下代理 Svelte-kit

javascript - Vue有什么用,它使开发人员可以在DOM元素上使用class属性?

javascript - 如果我使用 translateX(100%),在繁重的 javascript 函数期间,css 动画将停止

javascript - 如何通过javascript传递解析json值

javascript - 编写一个函数,返回数组 Javascript 中所有项目的平均值

javascript - 如何使用 Javascript 将图像对象转换为文件对象

javascript - 减慢 jQuery JSON 解析速度?