【问题标题】:Svelte on:change runs too lateSvelte on:改变来得太晚
【发布时间】:2021-04-09 02:47:08
【问题描述】:

我有一个 Svelte 应用程序:

  1. 可让您选择要查看的图表(饼图/条形图/日历)的下拉菜单
  2. 带有要包含在图表中的变量的复选框面板。 (不同的图表有不同的可用变量)
  3. 该函数仅针对所选变量过滤我的数据,然后将该数据传递到图表。

您可以在此处运行的完整代码:

<script>
  let rawData = {
    LevelTracker: [{ text: "headache" }, { text: "pain" }],
    EventType: [{ text: "coffee" }, { text: "aspirin" }],
    Event: [
      { time: 1500000000, text: "coffee" },
      { time: 1500030000, text: "aspirin" },
      { time: 1500230000, text: "coffee" },
      // etc....
    ],
    LevelChange: [
      { time: 1500000000, text: "headache", level: 2 },
      { time: 1500030000, text: "headache", level: 3 },
      { time: 1500230000, text: "pain", level: 2 },
      // etc....
    ],
  };

  $: availableLTs = rawData.LevelTracker.map((e) => e.text);
  $: availableETs = rawData.EventType.map((e) => e.text);

  let schemas = [
    {
      name: "byTimeOfDay",
      vars: [{ name: "X", et: true, lt: true }],
    },
    {
      name: "lagBarChart",
      vars: [
        { name: "X", min: 1, et: true, lt: false },
        { name: "Y", min: 1, max: 1, lt: true, et: true },
      ],
    },
    {
      name: "calendar",
      vars: [{ name: "X", et: true, lt: true }],
    },
  ];
  let chartsMap = {};
  for (let schema of schemas) {
    chartsMap[schema.name] = schema;
  }
  //let selectedChart = "lagBarChart";
  //let selectedChart = "byTimeOfDay";
  let selectedChart = "calendar";

  function getInitSelectedVars(schemaVars) {
    let selection = {};
    for (let varSchema of schemaVars) {
      selection[varSchema.name] = { ets: [], lts: [] };
    }
    return selection;
  }

  function initSelectedVars() {
    console.log("in initSelectedVars");
    selectedVars = getInitSelectedVars(schemaVars);
  }

  function makeChartData({ selectedVars, rawData }) {
    console.log("in makeChartData");
    for (let [key, value] of Object.entries(selectedVars)) {
      // TODO: we filter rawData for just the selected vars, and return that data...
    }
  }

  // this will be passed to the chart component
  $: chartData = makeChartData({
    selectedVars,
    rawData,
  });

  $: schemaVars = chartsMap[selectedChart].vars;

  $: selectedVars = selectedVars || getInitSelectedVars(schemaVars);
</script>

<main>
  <h2>Select chart type</h2>
  <select bind:value={selectedChart} on:change={initSelectedVars}>
    {#each schemas as chart}
      <option value={chart.name}>
        {chart.name}
      </option>
    {/each}
  </select>

  <h2>Select your vars</h2>

  {#each schemaVars as schemaVar}
    <h3>
      {schemaVar.name}
    </h3>
    {#if schemaVar.lt}
      {#each availableLTs as ele}
        <div class="form-check">
          <label>
            <input
              type="checkbox"
              class="form-check-input"
              bind:group={selectedVars[schemaVar.name].lts}
              value={ele}
            />
            {ele}
          </label>
        </div>
      {/each}
    {/if}
    {#if schemaVar.et}
      {#each availableETs as ele}
        <div class="form-check">
          <label>
            <input
              type="checkbox"
              class="form-check-input"
              bind:group={selectedVars[schemaVar.name].ets}
              value={ele}
            />
            {ele}
          </label>
        </div>
      {/each}
    {/if}
  {/each}

  <!-- then we display the selected chart, like:
     <calendar {chartData} />
   -->
</main>

<style>
</style>

每次用户更改下拉菜单时,我们都需要将 selectedVars 重新初始化为与当前图表架构匹配的值。

例如,如果选择了日历,我们需要这样做:

selectedVars = {X: {ets: [], lts: []}}

但是如果选择了barchart,我们需要:

selectedVars = {X: {ets: [], lts: []}, Y: {ets: [], lts: []}}

我定义了一个执行此操作的函数,并将on:change={initSelectedVars} 放在图表下拉列表中。但是,每次我将图表类型从“日历”更改为“条形图”时,我的makeChartData 中仍然出现错误:

Uncaught (in promise) TypeError: Cannot read property 'lts' of undefined
    at Object.mount [as m] (Debug.svelte:101)
    at Object.mount [as m] (Debug.svelte:95)
    at Object.mount [as m] (Debug.svelte:109)
    at Object.update [as p] (Debug.svelte:90)
    at update (index.mjs:764)
    at flush (index.mjs:732)

我认为 on:change 函数只有在 selectedVars 更改后才会运行,所以为时已晚。

有什么建议吗?我的代码如下。

【问题讨论】:

    标签: javascript svelte


    【解决方案1】:

    您确定错误发生在makeChartData 函数中吗?
    可能是这一行:bind:group={selectedVars[schemaVar.name].lts}

    我还没有完全理解你的代码,但是应该可以使用响应式语句将selectedVars 的值更改为所需的值。所以,我认为您不需要 on:change 处理程序。

    编辑: 我想你想要这样的东西:https://svelte.dev/repl/57d760278e0e4acfad536c1269bceba3?version=3.37.0

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-17
      • 1970-01-01
      • 2011-04-01
      • 2021-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多