【问题标题】:Correct way to mutate a component property in blazor在 blazor 中改变组件属性的正确方法
【发布时间】:2020-04-10 09:38:47
【问题描述】:

我有两个组件,Child.razorParent.razor

Child.razorHTML:

<input type="text" value="@Text" />

Child.razorC#:

[Parameter] public string Text { get; set; }

还有Parent.razor HTML:

<Child @ref="child_1" />
<Child @ref="child_2" />
<Child @ref="child_3" />

Parent.razorC#:

Child child_1;
Child child_2;
Child child_3;

void SetText(Child item, string text)
{
    item.Text = text;
}

我在item.Text = text 收到警告:

警告 BL0005:不应在其组件之外设置组件参数“文本”。

经过一番谷歌搜索,我发现了这个问题:BL0005 - external parameter usage - why is a warning for that?

答案很好,但没有提供替代方案(github上的链接内容也不是很有帮助)。

从父组件改变组件参数的正确方法是什么?

编辑

再澄清一点:我知道我可以使用绑定,但我需要能够更改 SetText 方法中的值,将我想要变异的 Child 作为参数传递。绑定的问题是变量没有与组件绑定。换句话说:对于 Child 的引用,我不知道应该设置哪个绑定字符串。

例如:

<Child @ref="child_1" @Text="binding_1" />
<Child @ref="child_2" @Text="binding_2"/>
<Child @ref="child_3" @Text="binding_3"/>

Parent.razorC#:

Child child_1;
Child child_2;
Child child_3;

string binding_1;
string binding_2;
string binding_3;

void SetText(Child item, string text)
{
     // which binding string should I set?
}

我可以可视化一些时髦的代码,创建一个Dictionary&lt;Child, string&gt; 以将组件与绑定字符串相关联,或者类似的东西,但是......真的吗?

【问题讨论】:

  • 嗯,我认为这很明显。 &lt;Child @ref="child_1" @Text="ParentSth" /&gt; 然后修改ParentSth 属性
  • @Eldar 在我的示例中,如何在 SetText 方法中使用绑定?
  • 抱歉,我在第一次评论时错过了绑定部分。您可以像这样将您的 parentProperty 绑定到子参数:&lt;Child @ref="child_1" @bind-Text="ParentSth" /&gt; 并且当您更改父项中的 ParentSth 属性时,它将反映给子项。
  • @Eldar 感谢您的评论。请看我的编辑

标签: c# asp.net-core razor blazor


【解决方案1】:

你可以在父组件中定义一个Child类型的属性 将父组件 (this) 的引用传递给 Parent 类型的子组件属性。现在子组件持有对父组件的引用,它可以将自己(再次使用它)添加到父组件。现在您有了对子组件的引用,您可以将其 Text 属性设置为一些有趣的东西。我希望我很清楚,如果不是,我会发布代码来反映这一点。以下代码有效...

Child.razor

<input type="text" value="@Text" />

@code
{
    [Parameter] public string Text { get; set; }
    public void SetText(string text)
    {
        Text = text;
        StateHasChanged();
    }
    [ParameterAttribute] public Parent Parent { get; set; }
    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            Parent.AddToParent(this);
        }
    }
}

注意在父组件(Text="Some Text")中分配的原始组件参数Text的值在文本框中不可见 因为在 Parent 的 SetText 方法调用 Child 的 SetText 方法之后立即将传递给它的值分配给 Text 属性,因此在文本框中看到的值是“新文本”

Parent.Razor

<Child Parent="this" Text="Some Text" />

@code{
    public void AddToParent(Child child)
    {
        string text = "new text";
        SetText(child, text);
    }

    void SetText(Child item, string text)
    {
        // which binding string should I set?
        item.SetText(text);

    }
}

用法

<Parent />

【讨论】:

  • 感谢您的回答。对于 Blazor,我发现需要在父母和孩子之间交换参考资料非常不幸,但我相信这是最好的方式。
  • 是的,这就是 Steve Anderson 创建 Tab 示例的方式。
  • 史蒂夫·桑德森 ;-)
  • 从架构上讲,这听起来像是一个糟糕的解决方案。父组件和子组件都将相互依赖,并且无法替代其他组件。
  • 如何检测 Blazor 中更改了哪个 ParameterAttribute 参数,或者我可以获取相同参数的旧值或新值?
【解决方案2】:

也许它可以提供帮助:

  1. 声明全局委托类型
    public delegate void OnInput(string v);
  1. 孩子
    <input type="text" @bind-value="@Value" />
    
    @code {
        [Parameter]
        public OnInput oninput { get; set; }
        [Parameter]
        public string Value
        {
            get
            {
                return v;
            }
            set
            {
                v = value;
                if (oninput!=null) oninput(value);
            }
        }
        private string v;
    }
  1. 父母
    <Child Value=@binding_1 OnInput=@((__v)=>{binding_1=__v;})/>
    <Child Value=@binding_2 OnInput=@((__v)=>{binding_2=__v;})/>
    <Child Value=@binding_3 OnInput=@((__v)=>{binding_3=__v;})/>
    @code {
        public string binding_1=new string("default value 1");
        public string binding_2=new string("default value 2");
        public string binding_3=new string("default value 3");
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-11
    • 2021-01-21
    • 1970-01-01
    • 1970-01-01
    • 2018-04-02
    • 1970-01-01
    • 2017-11-02
    • 1970-01-01
    相关资源
    最近更新 更多