Svelte子组件发生变化后,父组件如何重新执行函数?

问题描述 投票:0回答:1

我有一个简洁的代码。我想实现一个子组件更新后父组件重新执行的功能。 我现在遇到一个问题,子组件更新后,父组件函数重新触发,但是会进入死循环

父组件

<script lang="ts">
  import { Button } from "$lib/components/ui/button";
  import { SquarePlus } from "lucide-svelte";
  import Datatable from "$lib/components/datatable/datatable.svelte";
  import { getUserListAPI } from "@/apis/hook";
  import type { User, UserFilter } from "@/interfaces/user";
  import { onMount } from "svelte";
  let data: User[] = [];
  let dataSize = 0;
  
  let tableFilterDetail:UserFilter = {
    pageIndex:1,
    pageLimit:10
  }
  const getData = async (req:UserFilter) => {
    //AXIOS post get remote data
    const res = await getUserListAPI(req);
    data = res.data.rows;
    dataSize = res.data.count;
  };
  onMount(()=>{
    getData(tableFilterDetail)
  })
  $:{
    getData(tableFilterDetail)
  }
</script>

<div>
  <div class="mb-2 w-full flex justify-between items-center">
    <h2 class="text-2xl font-bold tracking-tight">User</h2>
    <div class="flex items-center">
      <Button
        variant="success"
        class="ml-1 h-10 w-28 flex items-center justify-center rounded-lg "
      >
        <SquarePlus size="16" />New
      </Button>
    </div>
  </div>
  <Datatable {data} {columns} {dataSize} bind:tableFilterDetail/>
</div>

子组件

<script lang="ts">
......

  //update state and update tableAttr
  $: {
    datatableAttr.update((state) => ({
      ...state,
      hiddenColumn: hideForId,
    }));
    datatableAttr.update((state) => ({
      ...state,
      dataSize: dataSize,
    }));
    datatableAttr.update((state) => ({
      ...state,
      pageSize: pageSize,
    }));
    tableFilterDetail = {
      pageIndex: $datatableAttr.currentPage,
      pageLimit: $datatableAttr.pageSize.value,
    };
    tableData.set(data);
  }

</script>
......
    <div class="flex items-center space-x-2">
      <label for="itemsPerPage" class="text-gray-700">Page shows:</label>
      <Select.Root portal={null} bind:selected={pageSize}>
        <Select.Trigger class="w-[130px]">
          <Select.Value />
        </Select.Trigger>
        <Select.Content>
          <Select.Group>
            {#each tableSize as size}
              <Select.Item value={size.value} label={size.label}
                >{size.label}</Select.Item
              >
            {/each}
          </Select.Group>
        </Select.Content>
        <Select.Input name="" />
      </Select.Root>
    </div>
    <div class="flex items-center space-x-2">
      <Pagination.Root
        count={$datatableAttr.dataSize}
        perPage={$datatableAttr.pageSize.value}
        let:pages
        let:currentPage
        bind:page={$datatableAttr.currentPage}
      >
        <Pagination.Content>
          <Pagination.Item>
            <Pagination.PrevButton />
          </Pagination.Item>
          {#each pages as page (page.key)}
            {#if page.type === "ellipsis"}
              <Pagination.Item>
                <Pagination.Ellipsis />
              </Pagination.Item>
            {:else}
              <Pagination.Item>
                <Pagination.Link {page} isActive={currentPage == page.value}>
                  {page.value}
                </Pagination.Link>
              </Pagination.Item>
            {/if}
          {/each}
          <Pagination.Item>
            <Pagination.NextButton />
          </Pagination.Item>
        </Pagination.Content>
      </Pagination.Root>
    </div>
......

可以实现组件第一次加载时请求API,当表数据发生变化时再次请求API并更新表数据,不会进入死循环。

javascript frontend svelte svelte-component
1个回答
0
投票

您的孩子中的大型反应式 $: {} 语句将在花括号内的任何内容发生变化时重新运行,数据、存储、过滤器、状态等。因此,一旦它命中,它将处于循环因为过滤器在那里 我建议删除反应语句中对 tableFilterDetail 的任何引用,因为现在当数据更改时,它会更新该过滤器,而当该过滤器更改时,它会更新数据......

// update store and tableData when ONLY the data variable changes $: data && updateStore() const updateStore = () => { datatableAttr.update((state) => ({ ...state, hiddenColumn: hideForId, dataSize: dataSize, pageSize: pageSize, })); tableData.set(data); } // find some other way to update the tableFilterDetail when the filter changes

用于删除过滤器后更新过滤器

perPage={$datatableAttr.pageSize.value}

中的

Pagination
和(当前页面)必须来自
dataTableAttr
商店吗?难道它不能仅仅绑定到传入的
tableFilterDetail.pageLimit
吗?
如果是这样的话,只需来回推动过滤器,而无需使用商店。

bind:perPage={tableFilterDetail.pageLimit} bind:currentPage={tableFilterDetail.pageIndex}

	
© www.soinside.com 2019 - 2024. All rights reserved.