如何在 Svelte 上反应性地获取 clientwidth 绑定值?

How to get clientwidth binding values reactively on Svelte?

我假设 clientWidth 没有被动更新。

问题

我想在一行中将尽可能多的电子邮件放入收件人单元格。

为此,我一次添加一个电子邮件地址。如果文本超过单元格的宽度,我会删除最后添加的电子邮件。

但是,它不会更新包含电子邮件地址的元素的宽度。无论 if 条件如何,它最终都会插入所有电子邮件。

尝试次数

如果我做错了什么或有任何解决方案,请告诉我。谢谢!

<script>
    import { tick } from 'svelte';
    let recipients = ["aaaa@dsad.com", "djdosa@dsoad.com", "dksoadk@.com", "kofksodpofds@dsad.com"];
    let recipientDisplayList = [];

    let innerWidth = 0;
    let recipientsWidth = 0;

    $: {
        if(innerWidth) {
            setRecipientDisplayList();
        }
    }

    async function setRecipientDisplayList() {
        for(let i = 0; i < recipients.length; i++) {
            recipientDisplayList.push(recipients[i]);
            recipientDisplayList = recipientDisplayList; // https://svelte.dev/tutorial/updating-arrays-and-objects
            await tick(); // wait for pending state changes to be reflected
            console.log(recipients[i])
            if(recipientsWidth > innerWidth) {
                recipientDisplayList.pop();
                break;
            }   
        }
    }
</script>

<style>
    table {
        table-layout: fixed;
    }
    th, td, table {
        border-collapse: collapse;
        border: 1px solid #333333;
        width: 100%;
    }

    th, td {
        max-width: 300px;
        min-width: 100px;
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
    }

    .recipients {
        display: inline-block;
    }
</style>

<table>
    <tbody>
        <tr>
            <th>Sender</th>
            <th>Recipients</th>
        </tr>
        <tr>
            <td>Kouta Nakano</td>
            <td>
                <div bind:clientWidth={innerWidth}>
                    <span bind:clientWidth={recipientsWidth} class="recipients">
                        {#each recipientDisplayList as recipient}
                        {recipient},&nbsp
                        {/each}
                    </span>
                </div>
            </td>
        </tr>
    </tbody>
</table>

和你一样,我希望 recipientsWidthawait tick() 之后更新,但不能说为什么它的行为会有所不同

当将每个电子邮件地址包装在其自己的范围内且宽度绑定到 recipientsWidth 并跟踪范围的总和以及与容器的关系 div 时,它会起作用 REPL
但是为什么不使用 text-overflow: ellipsis; 呢,所以 可见邮件地址多了?

<script>
    import { onMount, tick } from 'svelte';
    let recipients = ["aaaa@dsad.com", "djdosa@dsoad.com", "dksoadk@.com", "kofksodpofds@dsad.com"];
    let recipientDisplayList = [];

    let innerWidth = 0;
    let recipientsWidth = 0;
    let recipentsWidthSum = 0;

    onMount(async () => {
        for(let recipient of recipients) {
            recipientDisplayList = [...recipientDisplayList, recipient]
            await tick()
            recipentsWidthSum += recipientsWidth
            if(recipentsWidthSum > innerWidth) {
                recipientDisplayList.pop()
                recipientDisplayList = recipientDisplayList
                break;
            }
        }
    })
</script>

<table>
    <tbody>
        <tr>
            <th>Sender</th>
            <th>Recipients</th>
        </tr>
        <tr>
            <td>Kouta Nakano</td>
            <td>
                <div class="client" bind:clientWidth={innerWidth}>
                    {#each recipientDisplayList as recipient, index}
                    <span bind:clientWidth={recipientsWidth} class="recipient">
                        {recipient},&nbsp
                    </span>
                    {/each}
                </div>
            </td>
        </tr>
    </tbody>
</table>


<style>
    table {
        table-layout: fixed;
    }
    th, td, table {
        border-collapse: collapse;
        border: 1px solid #333333;
        width: 100%;
    }

    th, td {
        max-width: 300px;
        min-width: 100px;
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
    }
    
    .client {
        border: 1px solid teal;
    }
    .recipient {
        display: inline-block;
        border: 1px solid magenta;
    }
</style>