zoukankan      html  css  js  c++  java
  • 通过Blazor使用C#开发SPA单页面应用程序(3)

    通过Blazor使用C#开发SPA单页面应用程序(1) - 简介及特点

    通过Blazor使用C#开发SPA单页面应用程序(2) - 开发环境

    通过Blazor使用C#开发SPA单页面应用程序(3) - 基础知识

    通过Blazor使用C#开发SPA单页面应用程序(4) - Ant Design Button

     

    今天我们来看看Blazor开发的一些基本知识。

    一、Blazor组件结构


     Blazor中组件的基本结构可以分为3个部分,如下所示:

    //Counter.razor
    //Directives section 指令部分 @page "/counter" //Razor HTML section Razor HTML部分 <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" onclick="@IncrementCount">Click me</button> //code sections 功能部分 @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }

      指令部分:

    • 路由   - @page
    • DI     - @inject
    • 导入库 - @using

      Razor HTML 部分:

            Razor HTML语法是C#代码与HTML的结合。此部分最终在浏览器中呈现。

      指令部分:

           件中的函数部分包含用户操作函数(事件方法),局部变量和从/向父/子组件传递的属性。

      当然如果愿意,这部分也可以单独写道类文件中。

    二、Blazor的属性和参数


       我们看看属性和参数,

    <button id="btnClickMe" class="btn btn-primary" 
    onclick="@IncrementCount">Click me</button>

      在这里,在按钮元素的id,class和onclick被称为HTML属性。

      类似地,组件的定义方式与HTML元素相同,

     //MyDemo.razor
    @page "/myDome"
    
    <h3>MyDemo</h3>
    
    <ChildComponent Title="来自MyDemo"></ChildComponent>

      在Child Component中,该属性Title与装饰的子组件函数部分中的属性匹配 [Parameter] 关键字。

    //ChildComponent.razor

    //Child Component <div> <p>标题 : @Title</p> </div> @code { [Parameter] private string Title { get; set; } }

     运行效果如下:

    三、Blazor的数据绑定


      Blazor的数据绑定同时提供了单向绑定和双向绑定两种机制。

      (一)单向绑定:

      单向绑定在Blazor中简单直接,无需任何UI刷新。还记得Counter示例吗,他显示了单向数据绑定,

    @page "/counter"
    
    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="@IncrementCount">Click me</button>
    
    @code {
        int currentCount = 0;
    
        void IncrementCount()
        {
            currentCount++;
        }
    }

      此处 @currentCount 值根据点击按钮的数量递增Click me。<p>标记元素中的值会自动刷新,无需任何组件刷新。

       (二)双向绑定:

     在Blazor中可以实现双向绑定,与一些流行的JS语言框架相比,Blazor为双向绑定提供了多种实现方式,Blazor可以优雅地进行编写。

     

     (1) @bind属性在Blazor中提供双向数据绑定。下面的示例复选框演示在同一组件中的bind属性,

    @page "/myDome"
    
    
    <span>请选择:</span>
    <input type="checkbox" @bind="myChecked" />
    <p>我选择了 : @myChecked.ToString()</p>
    
    
    @code {
        bool myChecked { get; set; } = true;
    }

       运行效果如下,是不是很简单,很优雅。

       再来一个控制样式表的例子看看,

    @page "/myDome"
    
    <p>
        <span>显示/隐藏:</span>
        <input type="checkbox" @bind="myChecked" />
    </p>
    <p style="display:@(myChecked ? "inline":"none")">看到我了</p>
    
    
    @code {
        bool myChecked { get; set; } = true;
    }

     (2) @bind属性在Blazor中提供双向数据绑定,但是只提供了默认的绑定事件,如果们想在不同的时机触发双向绑定该怎么办呢,别急同样很简单的,我们看看下面的代码,展示了几种绑定实例,

    @page "/myDome"
    
    <p>
        <span>onchange 方式一</span>
        <input @bind="changeString" />
    </p>
    <p>
        <span>onchange 方式二</span>
        <input type="text"
               value="@changeString"
               @onchange="@((UIChangeEventArgs _e) => changeString = _e.Value.ToString())" />
    </p>
    <p>
        <span>onchange 方式三</span>
        <input @bind-value="changeString" @bind-value:event="onchange" />
    </p>
    <p>
        <span>oninput</span>
        <input @bind-value="changeString" @bind-value:event="oninput" />
    </p>
    <p>这是我输入的内容: @changeString</p>
    
    @code {
        string changeString = "";
    }

      运行效果如下,

        呈现组件时, input元素value的值来自changeString。 当用户在文本框中键入内容并离开时, 将触发事件onchange更改changeString的值。原则上, @bind将表达式的当前值value与changeString相关联, 并使用注册的处理程序来处理更改。
        除了使用@bind语法处理onchange事件之外, 还可以通过使用event参数 (@bind-value:event) 指定@bind-value属性, 使用其他事件来绑定属性或字段。例如第四个文本框就是绑定changeString采用oninput事件的属性,以到达在文本框的值更改时激发。

       (三)组件之间绑定:  

     (1)绑定可识别组件参数, @bind-{property}可在其中跨组件绑定属性值。

    //MyDemo.razor
    
    @page "/myDome"
    
    <h1>Parent Component</h1>
    <p>当前时间: @ParentNow</p>
    <hr />
    
    <ChildComponent @bind-Now="ParentNow" />
    
    <hr />
    <button class="btn btn-primary" @onclick="@ChangeTheYear">
        更新当前时间
    </button>
    
    @code {
        [Parameter]
        public DateTime ParentNow { get; set; } = DateTime.Now;
    
        private void ChangeTheYear()
        {
            ParentNow = DateTime.Now;
        }
    }
    //ChildComponent.razor
    
    <h2>Child Component</h2>
    
    <p>当前时间: @Now</p>
    
    @code {
        [Parameter]
        public DateTime Now { get; set; }
    
        [Parameter]
        public EventCallback<DateTime> NowChanged { get; set; }
    }

       以上代码中,子组件 (ChildComponent) 具有一个Now组件参数和NowChanged回调参数,父组件MyDemo使用ChildComponent并将ParentNow参数从父级绑定到子组件上Now的参数上,如果通过点击MyDemo中的"更新当前时间"按钮来更改属性的值, Now则将更新ChildComponent属性,将新值呈现在 UI中。其中,参数Now是可绑定的, 因为它具有NowChanged与参数类型匹配的伴随事件。按照约定,其等效于

    <ChildComponent @bind-Now="ParentNow" @bind-Now:event="NowChanged" />

      运行效果:

     (2)组件之间传递的数据通过组件属性及其属性映射发生,此方法使用委托Action<T>类型。

    //MyDemo.razor
    
    @page "/myDome"
    
    <h3>Parent Component</h3>
    <p>来自Child组件: @childString</p>
    <p>
        <input @bind="inputText" />
    </p>
    <hr />
    <ChildComponent ToChild="@inputText"
                    FromChild="@ReceivedFromChild">
    </ChildComponent>
    
    @code{
        private string inputText = "";
        private string childString = "";
    
    
        private void ReceivedFromChild(string str)
        {
            childString = str;
            StateHasChanged();
        }
    }
    //ChildComponent.razor
    
    <h4>Child Component</h4>
    <p>
        <input @bind="inputText" />
        <button @onclick="@PassToParent">显示到Parent组件</button>
    </p>
    <p>来自Parent组件 : @ToChild</p>
    
    @code{
        [Parameter]
        private string ToChild { get; set; }
    
        [Parameter]
        Action<string> FromChild { get; set; }
    
        private string inputText = "";
    
        private void PassToParent()
        {
            FromChild(inputText);
        }
    }

       这里FromChild是ChildComponent中的属性,属性使用Action<string>数据类型将值从Child传递给Parent Component。在Parent中,有相应的接收器函数ReceivedFromChild和字符串参数,这将在ChildComponent中按钮单击并触发通知时触发PassToParent,但是为了通知状态已在父组件中更改,我们使用StateHasChanged()的内置Blazor函数通知组件其状态已更改。

      运行效果如下:

    四、 生命周期方法


     (1) OnInitializedAsync和OnInitialized方法,执行代码来初始化组件。要执行异步操作,请在操作上使用OnInitializedAsync和await关键字。

    (2)OnParametersSetAsync和OnParametersSet当组件已接收到的参数从其父和值被分配给属性被调用。这些方法在组件初始化后以及每次呈现组件时执行。

    (3)OnAfterRenderAsync并OnAfterRender在组件完成渲染后调用。此时填充元素和组件引用。使用此阶段使用呈现的内容执行其他初始化步骤,例如激活对呈现的DOM元素进行操作的第三方JavaScript库。

    五、级联值和参数


     

      在某些情况下, 使用组件参数将数据从祖先组件流式传输到附属组件是不方便的, 尤其是在有多个组件层时。 级联值和参数通过提供一种方便的方法, 使上级组件为其所有子代组件提供值。 级联值和参数还提供了一种方法来协调组件。

      Blazor提供了一种在整个RenderTree(所有组件)中传递数据的方法,使用CascadingValue和CascadingParameter不需要传递作为组件属性,并且可以通过装饰属性[CascadingParameter]而不用在RenderTree(子组件)中接收值[Parameter]。

    //MyDemo.razor
    
    @page "/myDome"
    
    <p><span>姓名:</span><input @bind="@pName" /></p>
    <p><span>年龄:</span><input @bind="@pAge" /></p>
    <hr />
    <CascadingValue Value="@pName" Name="ProfileName">
        <CascadingValue Value="@pAge" Name="ProfileAge">
            <ParentComponent />
        </CascadingValue>
    </CascadingValue>
    
    @code {
        private string pName { get; set; } = "张三";
        private int pAge { get; set; } = 35;
    }
    //ParentComponent.razor
    
    <div style="background-color:darkgray">
        <p>Parent Component</p>
        <div style="padding:10px;">
            <ChildComponent />
        </div>
    </div>
    //ChildComponent.razor
    
    <div style="background-color:beige">
        <p>Child Component</p>
        <p>输入的 姓名: @Name  , 年龄 : @Age.ToString()</p>
    </div>
    
    @code{
        [CascadingParameter(Name = "ProfileName")]
        string Name { get; set; }
        [CascadingParameter(Name = "ProfileAge")]
        int Age { get; set; }
    }

      代码中MyDemo的姓名、年龄穿透ParentComponent直接级联到ChildComponent中。

      在这里CascadingParameter,Name参数必须与Name带有CascadingValue组件的属性匹配,如果我们没有提到任何Name,则CascadingParameter中的变量类型与CascadingValue中的Value属性匹配。

      运行效果:

     

    六、路由


      我们在看一个SPA中一个基本但很重要的功能路由。客户端路由可以通过使用@page指令装饰组件来在Blazor中完成。

    @page "/myDome"
    @page "/myDome/{text}"

      @page在上面的示例中应用了两个指令。

      第一个允许在没有参数的情况下导航到组件。

      第二个@page指令采用{text}route参数并将值赋给Text属性。

    好了今天Blazor的组件开发就先学习到这,有意犹未尽的可以查看官方文档深入学习。

  • 相关阅读:
    Android-监听操作系统短信
    Android-Observer(内容观察者)
    Android-ContentProvider读取/新增/操作系统联系人数据
    Android-ContentProvider原理图
    Android-ContentProvider-UriMatcher
    Android-ListView-CursorAdapter
    Android-ListView-SimpleCursorAdapter
    openssl可以实现:秘钥证书管理、对称加密和非对称加密
    网址收藏
    php 通用数据库类
  • 原文地址:https://www.cnblogs.com/liuxtj/p/11350992.html
Copyright © 2011-2022 走看看