Blazor Component TwoWay Databinding - PullRequest
1 голос
/ 14 мая 2019

Я сделал компонент Blazor следующим образом:

<input bind-value-oninput="Title" />


@functions {

    [Parameter] string Title { get; set; }

    [Parameter] EventCallback<string> TitleChanged { get; set; }
}

Родитель:

@page "/fetchdata"

Parent:<input bind-value-oninput="Title" /> - Child:<Comp bind-Title="Title"></Comp>



@functions {
    string Title;

}

Как и ожидалось, редактирование родительского ввода распространяет его значение на компонент, но не наоборот, это так, верно?

Я достиг двустороннего поведения с этим редактированием:

<input bind-value-oninput="Title" />


@functions {
    string _Title { get; set; }
    [Parameter] string Title 

    {
        get { return _Title; }
        set
        {
            Console.WriteLine($"{value}->{_Title}");



            if (_Title != value)
            {
                _Title = value;
                TitleChanged.InvokeAsync(value);
            }


        }
    }

    [Parameter] EventCallback<string> TitleChanged { get; set; }
}

Является ли это наилучшей практикой для достижения двустороннего связывания данных? Тогда TitleChanged должен вызываться вручную, верно? Это как PropertyChanged из WPF?

Без

     if (_Title != value)

код идет в цикле, кто-то может объяснить, почему?

1 Ответ

1 голос
/ 14 мая 2019

Это двусторонняя привязка данных между компонентами. Такое поведение (или ограничение) является намеренным. То, что вы делаете, - это правильный способ ее решения, и я могу рискнуть сказать, что передовая практика, по крайней мере, по мнению Стива Андерсона, может предложить другие методы, например, класс обслуживания.

Некоторое объяснение того, что происходит: когда вы применяете изменение к родительскому компоненту, происходит событие изменения, состояние компонента изменилось, и компонент должен быть повторно обработан. Для повторного рендеринга родительского компонента метод StateHasChanged автоматически вызывается Blazor. Но когда состояние дочернего компонента изменяется, родительский компонент об этом не знает, и мы должны уведомить об этом. Опять же, использование обратных вызовов для этого является хорошей практикой, на мой взгляд ...

Надеюсь, это поможет ....

Редактировать ....

Обычно поток параметров идет вниз, то есть от родителя к дочерний, а не в другом направлении, потому что поток рендеринга идет в это направление. Вот почему нет способа передачи параметров вверх по течению (например, в макет), потому что тогда не будет ни одного определенный порядок рендеринга.

SteveSanderson

Марко: Я не понимаю, почему при вызове StateHasChanged для родителя данные передаются от родителя к ребенку, а не наоборот.

Во-первых, вы не вызываете метод StateHasChanged вручную. Он автоматически вызывается всякий раз, когда срабатывает входное событие; то есть после нажатия каждой клавиши клавиатуры. И это вызвано, чтобы повторно представить Компонент (родитель). (Примечание: заманчиво думать, что тег ввода является элементом тега ввода HTML, но это не так.)

А почему не наоборот? Думаю, цитата SteveSanderson прояснила ситуацию.

Когда вы хотите передать значение (это на самом деле параметр, но не свойство Attribute) в родительский компонент, вам нужно использовать другой механизм, такой как события (рекомендуется SteveSanderson; и работать так же, как в Angular ). Ниже приведен пример кода, как это выполняется. Важное замечание: Когда состояние родительского компонента изменяется от дочернего компонента, мы должны сообщить родительскому компоненту, что его состояние изменилось и что его следует перерисовать, вручную вызвав метод StateHasChanged. Это верно при использовании делегата Action, хотя я думаю, что делегат EventCallback должен автоматически вызывать StateHasChanged.

Компонент A.cshtml

// Define a method in the parent component which will be called 
// from the child component when the user tap the button residing 
// in the child component. This method has a string parameter passed
// from the child component
public void GetValueFromChild(string value)
 {
        // Do somethig with value
  } 

Компонент B.cshtml

// When the user click the button the method GetValueFromChild
// defined on the parent component is called

<button class="btn" onclick=@(() => OnAddValue("some string value"))>Add</button>

    @functions
{
    // Define an Action delegate property which stores a reference
    // to A.GetValueFromChild
    // Parameters
    [Parameter] Action<string> OnAddValue{ get; set; }
}

A.cshtml

// Here (in the parent component) you place the child component and
// set its OnAddValue to the name of the method to be called
<B OnAddValue = "GetValueFromChild"></B> 

Пожалуйста, отметьте мой ответ как принятый, если он вам помог Надеюсь, это поможет ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...