Blazor - 为什么双向绑定适用于 List 而不是自定义组件中的 String?

Blazor - why does two way binding work for List but not String in custom component?

所有关于使用双向绑定的文档都声称,为了在自定义组件中进行双向绑定,您需要使用 EventCallback。然而,当使用 List 时,它会自动工作。我想知道为什么?

示例页面 index.razor:

@page "/"

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt ListOfValues="@ListOfValues" StringValue="@StringValue" />

<div @onclick="WriteValues">then click me</div>


@code {
    List<string> ListOfValues { get; set; } = new();
    public string StringValue { get; set; } = "";
    private void WriteValues()
    {
        foreach(var v in ListOfValues){
            Console.WriteLine($"ListOfValues: {v}");
        }
        Console.WriteLine($"StringValue: {StringValue}");
    }
}

示例组件 SurveyPrompt.razor:

<div class="alert alert-secondary mt-4">
   
    <div @onclick="bubu">click me</div>
   
</div>

@code {
    [Parameter] public List<string> ListOfValues { get; set; } = new();
    [Parameter] public string StringValue { get; set; } = "";

    private void bubu()
    {
        ListOfValues.Add("First Value set in a component");
        ListOfValues.Add("Second Value set in a component");
        
        StringValue = "A Value set in a component";
    }
}

当 运行 应用程序点击“点击我”,然后点击“然后点击我”时,控制台将显示 ListOfValues 变量的值在 index.razor 中已填写 SurveyPrompt.razor 但 StringValue 仍为空

页面外观:

单击“单击我”然后单击“然后单击我”后控制台的外观:

List<T> 的情况下,您观察到的不是绑定效果。发生的情况是,在您的 index.razor 页面中,您创建了一个列表 (ListOfValues),然后将其传递给您的 SurveyPrompt。请注意,您不复制列表,而是通过引用传递它。 index.razorSurveyPrompt 都“共享”同一个列表实例。因此,当您对列表进行更改时,它们对保持对它的引用的所有内容都是可见的。

不过,字符串是不可变的。当你改变字符串时,你并没有修改原来的字符串,而是在内存中创建一个新的字符串来替换旧的字符串。结果,修改后,index.razorSurveyPrompt有两个单独的字符串。