简体   繁体   English

当我的道具发生变化时,如何在 Svelte 中强制重新渲染?

[英]How do I force a rerender in Svelte when my props changes?

I have a totaling component that needs to total the same index of multiple arrays in a multidimensional array, similar to totaling columns in a spread sheet.我有一个总计组件需要在多维数组中总计多个 arrays 的相同索引,类似于电子表格中的总计列。 I have a different component that allows me to change the values in the arrays, and also totals the rows in the spreadsheet.我有一个不同的组件,它允许我更改 arrays 中的值,并汇总电子表格中的行。 I'm having troubles with the totaling component re-rendering and/or updating the columns total after a change to the array.我在对数组进行更改后重新渲染和/或更新列总数时遇到问题。 I thought I might need to do a reactive declaration in my totaling component, but that doesn't seem to be working.我想我可能需要在我的总计组件中做一个反应性声明,但这似乎不起作用。

Here's a link to the REPL.这是REPL 的链接。

And here's the code:这是代码:

Totals.svelte

<script>
    export let jobs

      //this creates a new array which is two indexes long for each of the columns
      //then fills each array with the sum of column
      //HOW DO I GET THIS TO UPDATE EACH TIME A JOB HOURS ENTRY IS CHANGED?
    $: totals = new Array(2).fill(null).map((v, i) => {
    let total = 0;
    jobs.jobHours.forEach((v) => {
      total += Number(v[i]);
    });
    return total;
  });

    //this sums the total hours row to give the grand total
    //HOW DO I GET THIS TO UPDATE EACH TIME THE TOTALS VARIABLE IS CHANGED?
  $: grandTotal = totals.reduce((acc, v) => (acc += v));        

</script>

<style>
  container {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1fr;        

  }
  div {
    width: 100%;
    height: 100%;    
    width: 150px;
  }
</style>

<container>
  <div>Total Hours</div>
  {#each totals as total}
  <div>
    {total}
  </div>
  {/each}
  <div>{grandTotal}</div>
</container>
App.svelte

<script>
    import JobEntries from './JobEntries.svelte';
    import Totals from './Totals.svelte';

    const jobs = {
        jobNames: ['Job1', 'Job2', 'Job3'], 
        jobHours: Array.from(Array(3), () => Array.from(Array(2), ()=>1))
    };
</script>

<JobEntries {jobs}/>
<Totals {jobs} />

JobEntries.svelte

<script>
    export let jobs
    let cell = Array.from(Array(3), () => Array.from(Array(3)));
</script>

<style>
  container {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1fr;

  }
  input, div {
    width: 100%;
    height: 100%;
    min-width: 150px;
  }
</style>

<container>
    <div>
        Name
    </div>  
    <div>
        Time 1
    </div>
    <div>
        Time 2
    </div>
    <div>
        Total
    </div>
  {#each jobs.jobNames as name, i}
            <input
                type="text"                
                bind:this={cell[i][0]}
                bind:value={name}            />
        {#each jobs.jobHours[i] as hour, j}
            <input
                type="number"                
                bind:this={cell[i][j+1]}
                bind:value={hour}
            />
        {/each}
    <div>
        {jobs.jobHours[i].reduce((acc,v)=>acc+=v)}
    </div>
  {/each}
</container>

Binding the prop in the parent component, allows the prop to be changed by the child component.在父组件中绑定 prop,允许子组件更改 prop。

App.svelte

<script>
    import JobEntries from './JobEntries.svelte';
    import Totals from './Totals.svelte';
    let jobs = {
        jobNames: ['Job1', 'Job2', 'Job3'], 
        jobHours: Array.from(Array(3), () => Array.from(Array(2), ()=>1))
    };
</script>

<JobEntries bind:jobs/>
<Totals {jobs} />

JobEntries.svelte

<script>
    export let jobs 
    let cell = Array.from(Array(3), () => Array.from(Array(3)));

</script>

<style>
  container {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1fr;

  }
  input, div {
    width: 100%;
    height: 100%;
    min-width: 150px;
  }
</style>

<container>
    <div>
        Name
    </div>  
    <div>
        Time 1
    </div>
    <div>
        Time 2
    </div>
    <div>
        Total
    </div>
  {#each jobs.jobNames as name, i}
        <input
            type="text"                
            bind:this={cell[i][0]}
            bind:value={name}            />
        {#each jobs.jobHours[i] as hour, j}
            <input
                type="number"                
                bind:this={cell[i][j+1]}
                bind:value={hour}
            />
        {/each}
    <div>
        {jobs.jobHours[i].reduce((acc,v)=>acc+=v)}
    </div>
  {/each}
</container>

Alexander's comment got me thinking about jobs in App.svelte not actually being updated, and how I could accomplish that. Alexander 的评论让我想到了App.svelte中的jobs实际上并未更新,以及我如何才能做到这一点。 With Svelte's event dispatch , I can have the child component dispatch the updated prop back to the parent component, and on receiving the message, update jobs in App.svelte .使用 Svelte 的event dispatch ,我可以让子组件将更新的 prop 发送回父组件,并在收到消息后更新App.svelte中的jobs Although I agree a Svelte store is probably a better way to handle state, this problem is solvable without a store.虽然我同意 Svelte 商店可能是处理 state 的更好方法,但这个问题可以在没有商店的情况下解决。 Below is the code.下面是代码。

App.svelte

<script>
    import JobEntries from './JobEntries.svelte';
    import Totals from './Totals.svelte';

    const jobs = {
        jobNames: ['Job1', 'Job2', 'Job3'], 
        jobHours: Array.from(Array(3), () => Array.from(Array(2), ()=>1))
    };
</script>

<JobEntries {jobs} on:message={e=>jobs.jobHours = e.detail}/>
<Totals {jobs} />
JobEntries.svelte

<script>
    import { createEventDispatcher } from 'svelte';
    export let jobs 
    const dispatch = createEventDispatcher();    

    let cell = Array.from(Array(3), () => Array.from(Array(3)));

</script>

<style>
  container {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1fr;

  }
  input, div {
    width: 100%;
    height: 100%;
    min-width: 150px;
  }
</style>

<container>
    <div>
        Name
    </div>  
    <div>
        Time 1
    </div>
    <div>
        Time 2
    </div>
    <div>
        Total
    </div>
  {#each jobs.jobNames as name, i}
            <input
                type="text"                
                bind:this={cell[i][0]}
                bind:value={name}            />
        {#each jobs.jobHours[i] as hour, j}
            <input
                type="number"                
                bind:this={cell[i][j+1]}
                bind:value={hour}
                on:input={e=>dispatch('message', jobs.jobHours)}
            />
        {/each}
    <div>
        {jobs.jobHours[i].reduce((acc,v)=>acc+=v)}
    </div>
  {/each}
</container>
Totals.svelte

<script>
    export let jobs

      //this creates a new array which is two indexes long for each of the columns
      //then fills each array with the sum of column     
    $: totals = new Array(2).fill(null).map((v, i) => {
    let total = 0;
    jobs.jobHours.forEach((v) => {
      total += Number(v[i]);
    });
    return total;
  });

    //this sums the total hours row to give the grand total
  $: grandTotal = totals.reduce((acc, v) => (acc += v));        

</script>

<style>
  container {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1fr;        

  }
  div {
    width: 100%;
    height: 100%;    
    width: 150px;
  }
</style>

<container>
  <div>Total Hours</div>
  {#each totals as total}
  <div>
    {total}
  </div>
  {/each}
  <div>{grandTotal}</div>
</container>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如果我的道具在 React 中发生变化,如何更新 state 以强制重新渲染? - How do I update the state to force a rerender if my props change in React? Svelte.js - 如何使用新道具重新渲染子组件? - Svelte.js - How to rerender child components with new props? 使用ReactJs,当从props发送的父对象发生更改时,如何更新表单字段? - Using ReactJs, How do I update my form fields when my parent object sent in from props changes? 你如何强迫Ember重新渲染一个组件? - How do you force Ember to rerender a component? 从列表中删除后如何重新渲染我的屏幕? - How do i rerender my screen after deletion from list? 当 State 更改时,如何使反应组件重新渲染? - How do I make react component rerender when the State is changed? 如何使用所有相对路径构建我的 Svelte 网站? - How do I build my Svelte website with all relative paths? 当状态改变时,React 不会重新渲染我的组件 - React wont rerender my component when state changes 如何使 if 语句重新渲染组件苗条 - How to make if statement rerender component svelte 当输入值在其他模板上更改时,如何重新渲染火焰模板? - How can I rerender a blaze template when an input value changes on a different template?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM