zoukankan      html  css  js  c++  java
  • 2020-06-11-ASP.NET Core Blazor 子组件父组件数据同步的问题

    上一篇写数据绑定的文章,写到最后留了一个坑。当子组件绑定父组件的一个字段,并且子组件修改它的时候父组件不能实时进行同步更新UI的问题,最近终于在Blazui作者的指导下搞定了。

    UserInfo类要实现INotifyPropertyChanged接口

        public class UserInfo: INotifyPropertyChanged
        {
            private string _userName;
            public string UserName {
                get
                {
                    return _userName;
                }
                set
                {
                    _userName = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(UserName)));
                }
             }
    
            public string Sex { get; set; }
    
            public DateTime BrithDay { get; set; }
    
            public event PropertyChangedEventHandler PropertyChanged;
        }
    

    没想到微软blazor还是借用了WPF搞MVVM的模式,模型需要实现INotifyPropertyChanged类,在属性发生修改的时候可以发出通知。

    父组件订阅PropertyChanged事件:

    @page "/"
    ====================parent```==================
    
    <p>
        userName: @userInfo.UserName
    </p>
    <p>
        sex: @userInfo.Sex
    </p>
    <p>
        brithday: @userInfo.BrithDay
    </p>
    <p>
        title: @title
    </p>
    
    
    <InfoEdit UserInfo="userInfo" UserInfoChanged="HandleUserInfoChanged"></InfoEdit>
    
    @code {
    
        private UserInfo userInfo;
    
        private string title;
    
        protected override void OnInitialized()
        {
            userInfo = new UserInfo
            {
                UserName = "abc",
                Sex = "f",
                BrithDay = DateTime.Now
            };
            this.userInfo.PropertyChanged += (o, e) => StateHasChanged();
            base.OnInitialized();
        }
    
        private void HandleUserInfoChanged(UserInfo info)
        {
            this.userInfo = info;
    
            Console.WriteLine("HandleUserInfoChanged");
        }
    
    
    }
    
    

    父组件订阅子组件的PropertyChanged事件,当事件发生的时候调用组件的StateHasChanged方法。StateHasChanged方法会通知组件说状态发生变化了,也就是说组件会被重新渲染。这就是最关键的东西了。

    子组件

    ====================child==================
    
    <p>
        userName: <input @bind="UserInfo.UserName" @bind:event="oninput" />
    
    </p>
    
    <p>
        sex:
        <select @bind="UserInfo.Sex">
            <option value="m">男</option>
            <option value="f">女</option>
        </select>
    </p>
    
    <p>
        BrithDay:<input @bind="UserInfo.BrithDay" />
    </p>
    
    <button class="btn btn-danger" @onclick="InvokeChanged">保存</button>
    
    @code {
    
        [Parameter]
        public UserInfo UserInfo { get; set; }
    
        [Parameter]
        public EventCallback<UserInfo> UserInfoChanged { get; set; }
    
        private void InvokeChanged()
        {
            UserInfoChanged.InvokeAsync(this.UserInfo);
            Console.WriteLine("InvokeChanged");
        }
    
    }
    

    运行

    一些吐槽

    虽然搞定了子父组件同步的问题,但是我不能理解的是,为什么微软要搞的这么复杂。使用@bind-UserInfo会强制用户在子组件实现一个 EventCallback UserInfoChanged 事件。那么既然@bind:event="oninput"可以实时回写字段的值,那么为什么不直接同时调用UserInfoChanged对外抛事件呢?而且在父组件同样可以在编译器直接植入对UserInfoChanged事件的监听同时刷新UI。可能是微软为了性能,想要用户手工控制父组件的渲染时机吧。

    关注我的公众号一起玩转技术

  • 相关阅读:
    JFreeChart API 说明(转)
    杭电1064
    杭电2734
    杭电1170
    杭电1197
    杭电2629
    杭电1062
    杭电2088
    杭电1205
    杭电1004
  • 原文地址:https://www.cnblogs.com/kklldog/p/13095497.html
Copyright © 2011-2022 走看看