在 Blazor 的父组件中获取子组件绑定值
Get Child Component binded values in Parent Component in Blazor
假设名为 cinput.cshtml 的子组件是
<input type="text" bind="@username">
@functions{
string username;
}
父组件名为 pform.cshtml
<cinput></cinput>
<input type="text" bind="@email">
<input type="button" onclick="@onsubmit">
@functions{
string email;
public void onsubmit(){
//Call api
}
}
所以问题是如何在父组件中获取用户名值?
所以我做了这样的事情
cinput.cshtml
<input type="text" bind="@username">
@functions{
string username;
string getUsername(){
return username;
}
}
在pform.cshtml
<cinput ref="_cinput"></cinput>
<input type="text" bind="@email">
<input type="button" onclick="@onsubmit">
@functions{
string email;
Cinput _cinput
public void onsubmit(){
//get username
string uname = _cinput.getUsername();
//Call api
}
}
您应该执行以下操作:
- 在您的 Child 组件中定义一个 EventCallback 委托 属性:
[Parameter] protected EventCallback<string> OnUserNameChanged { get; set; }
此 属性 将包含对 Parent 组件上定义的方法的委托。
- 在您的 Child 组件中定义一个 属性 和一个支持变量:
private string username;
public string UserName
{
get => username;
set
{
username = value;
// Invoke the delegate passing it the changed value
OnUserNameChanged?.Invoke(value);
}
}
- 在您的 Parent 组件中定义一个方法,该方法在用户名更改时从 Child 组件调用:
public async void UserNameChanged(string username)
{
// Gets and consume the user name
}
- 这就是您的 Child 组件在 Parent 组件中的使用方式:
请注意,我们将方法名称分配给属性 OnUserNameChanged,它是您的 Child 组件
中的委托 属性
<cinput OnUserNameChanged="UserNameChanged" ></cinput>
<input type="text" bind="@email">
<input type="button" onclick="@onsubmit">
希望这对您有所帮助...
这是史蒂夫·安德森 (Steve Anderson) 对 ref 的评价:
用例
预期用例是允许 parent 组件向 child 组件发出命令,例如 "show" 或 "reset"。
即便如此,在架构上它也是一种妥协,因为如果 child 组件是无状态的(也就是说,不作用于除它们的参数),在这种情况下,除了更改它们的 child 参数之外,发出 "action" 在理论上是没有意义的,在这种情况下,您根本不需要 ref .
强烈不建议 使用 ref 作为改变 child 组件状态的方法。相反,始终使用普通的声明性参数将数据传递给 child 组件。这将导致 child 个组件在正确的时间自动 re-render。我们正在努力改变组件参数的表示方式,以便默认情况下它们被封装并且不可能从外部 read/write。
BLAZOR 方式:
要按照他们打算在 Blazor 中完成的方式执行此操作,请从使用 Blazor 组件开始。下面的示例使用组件 SingleSelect.razor,它是一个简化的 HTML Select 元素。
该组件由 VisualStudio 根据 razor 组件文件的名称自动生成的标记引用,因此在这种情况下,该标记将为 <SingleSelect>
。
为了从子组件获取值,父组件创建了一个指向子组件的引用变量。
这是通过在父级中创建子级的局部变量来完成的:
private SingleSelect singleSelect;
然后在子标签中链接它:
<SingleSelect @ref="singleSelect" Options="SingleSelectOptions"></SingleSelect>
这允许通过使用引用变量来引用子数据:
singleSelect.SelectedOption.Value
以下页面给出了完整示例。
Index.razor page
@page "/"
<h3>Single Select Example</h3>
<h5 class="mt-2">Make your selection</h5>
<SingleSelect @ref="singleSelect" Options="SingleSelectOptions"></SingleSelect>
<button class="btn btn-primary mt-2" @onclick="SubmitSingleSelect">Submit</button>
<h5 class="mt-2">The following was selected:</h5>
<p>@singleSelectResult</p>
@code
{
public partial class Index
{
SingleSelect singleSelect;
string singleSelectResult;
List<SingleSelectOption> SingleSelectOptions = new List<SingleSelectOption>
{
new SingleSelectOption{ Id=1, Value="One"},
new SingleSelectOption{ Id=2, Value="Two"},
new SingleSelectOption{ Id=3, Value="Three"},
new SingleSelectOption{ Id=4, Value="Four"},
new SingleSelectOption{ Id=5, Value="Five"},
new SingleSelectOption{ Id=6, Value="Six"},
new SingleSelectOption{ Id=7, Value="Seven"},
new SingleSelectOption{ Id=8, Value="Eight"},
new SingleSelectOption{ Id=9, Value="Nine"},
new SingleSelectOption{ Id=10, Value="Ten"},
new SingleSelectOption{ Id=11, Value="Eleven"},
};
private void SubmitSingleSelect()
{
singleSelectResult = singleSelect.SelectedOption.Value;
}
}
}
SingleSelect.razor page
<div class="container">
<div class="row">
<div class="col-3">
<select id="NotSelected" class="border" multiple="multiple" size="@boxSize" style="width: 200px">
@foreach (var option in Options)
{
<option id="@option.Id" @onclick="@(() => Select(option))">@option.Value</option>
}
</select>
</div>
</div>
</div>
@code
{
[Parameter]
public List<SingleSelectOption> Options { get; set; } = new List<SingleSelectOption>();
public SingleSelectOption SelectedOption { get; set; } = new SingleSelectOption { Id = 0, Value = " "};
private int boxSize = 5;
private void Select(SingleSelectOption option)
{
SelectedOption = option;
}
public class SingleSelectOption
{
public int Id { get; set; }
public string Value { get; set; }
}
}
假设名为 cinput.cshtml 的子组件是
<input type="text" bind="@username">
@functions{
string username;
}
父组件名为 pform.cshtml
<cinput></cinput>
<input type="text" bind="@email">
<input type="button" onclick="@onsubmit">
@functions{
string email;
public void onsubmit(){
//Call api
}
}
所以问题是如何在父组件中获取用户名值?
所以我做了这样的事情
cinput.cshtml
<input type="text" bind="@username">
@functions{
string username;
string getUsername(){
return username;
}
}
在pform.cshtml
<cinput ref="_cinput"></cinput>
<input type="text" bind="@email">
<input type="button" onclick="@onsubmit">
@functions{
string email;
Cinput _cinput
public void onsubmit(){
//get username
string uname = _cinput.getUsername();
//Call api
}
}
您应该执行以下操作:
- 在您的 Child 组件中定义一个 EventCallback 委托 属性:
[Parameter] protected EventCallback<string> OnUserNameChanged { get; set; }
此 属性 将包含对 Parent 组件上定义的方法的委托。
- 在您的 Child 组件中定义一个 属性 和一个支持变量:
private string username;
public string UserName
{
get => username;
set
{
username = value;
// Invoke the delegate passing it the changed value
OnUserNameChanged?.Invoke(value);
}
}
- 在您的 Parent 组件中定义一个方法,该方法在用户名更改时从 Child 组件调用:
public async void UserNameChanged(string username)
{
// Gets and consume the user name
}
- 这就是您的 Child 组件在 Parent 组件中的使用方式: 请注意,我们将方法名称分配给属性 OnUserNameChanged,它是您的 Child 组件 中的委托 属性
<cinput OnUserNameChanged="UserNameChanged" ></cinput>
<input type="text" bind="@email">
<input type="button" onclick="@onsubmit">
希望这对您有所帮助...
这是史蒂夫·安德森 (Steve Anderson) 对 ref 的评价:
用例
预期用例是允许 parent 组件向 child 组件发出命令,例如 "show" 或 "reset"。
即便如此,在架构上它也是一种妥协,因为如果 child 组件是无状态的(也就是说,不作用于除它们的参数),在这种情况下,除了更改它们的 child 参数之外,发出 "action" 在理论上是没有意义的,在这种情况下,您根本不需要 ref .
强烈不建议 使用 ref 作为改变 child 组件状态的方法。相反,始终使用普通的声明性参数将数据传递给 child 组件。这将导致 child 个组件在正确的时间自动 re-render。我们正在努力改变组件参数的表示方式,以便默认情况下它们被封装并且不可能从外部 read/write。
BLAZOR 方式:
要按照他们打算在 Blazor 中完成的方式执行此操作,请从使用 Blazor 组件开始。下面的示例使用组件 SingleSelect.razor,它是一个简化的 HTML Select 元素。
该组件由 VisualStudio 根据 razor 组件文件的名称自动生成的标记引用,因此在这种情况下,该标记将为 <SingleSelect>
。
为了从子组件获取值,父组件创建了一个指向子组件的引用变量。
这是通过在父级中创建子级的局部变量来完成的:
private SingleSelect singleSelect;
然后在子标签中链接它:
<SingleSelect @ref="singleSelect" Options="SingleSelectOptions"></SingleSelect>
这允许通过使用引用变量来引用子数据:
singleSelect.SelectedOption.Value
以下页面给出了完整示例。
Index.razor page
@page "/"
<h3>Single Select Example</h3>
<h5 class="mt-2">Make your selection</h5>
<SingleSelect @ref="singleSelect" Options="SingleSelectOptions"></SingleSelect>
<button class="btn btn-primary mt-2" @onclick="SubmitSingleSelect">Submit</button>
<h5 class="mt-2">The following was selected:</h5>
<p>@singleSelectResult</p>
@code
{
public partial class Index
{
SingleSelect singleSelect;
string singleSelectResult;
List<SingleSelectOption> SingleSelectOptions = new List<SingleSelectOption>
{
new SingleSelectOption{ Id=1, Value="One"},
new SingleSelectOption{ Id=2, Value="Two"},
new SingleSelectOption{ Id=3, Value="Three"},
new SingleSelectOption{ Id=4, Value="Four"},
new SingleSelectOption{ Id=5, Value="Five"},
new SingleSelectOption{ Id=6, Value="Six"},
new SingleSelectOption{ Id=7, Value="Seven"},
new SingleSelectOption{ Id=8, Value="Eight"},
new SingleSelectOption{ Id=9, Value="Nine"},
new SingleSelectOption{ Id=10, Value="Ten"},
new SingleSelectOption{ Id=11, Value="Eleven"},
};
private void SubmitSingleSelect()
{
singleSelectResult = singleSelect.SelectedOption.Value;
}
}
}
SingleSelect.razor page
<div class="container">
<div class="row">
<div class="col-3">
<select id="NotSelected" class="border" multiple="multiple" size="@boxSize" style="width: 200px">
@foreach (var option in Options)
{
<option id="@option.Id" @onclick="@(() => Select(option))">@option.Value</option>
}
</select>
</div>
</div>
</div>
@code
{
[Parameter]
public List<SingleSelectOption> Options { get; set; } = new List<SingleSelectOption>();
public SingleSelectOption SelectedOption { get; set; } = new SingleSelectOption { Id = 0, Value = " "};
private int boxSize = 5;
private void Select(SingleSelectOption option)
{
SelectedOption = option;
}
public class SingleSelectOption
{
public int Id { get; set; }
public string Value { get; set; }
}
}