<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Util 應用框架 UI 全新升級

      Util UI 已經(jīng)開發(fā)多年, 并在多家公司的項目使用.

      不過一直以來, Util UI 存在一些缺陷, 始終未能解決.

      最近幾個月, Util 團隊下定決心, 終于徹底解決了所有已知缺陷.

      Util 應用框架 UI 介紹

      Util 應用框架 UI 建立在 Angular , Ng-Zorro, Ng-Alain 基礎之上, 用于開發(fā)企業(yè)中后臺.

      Util 應用框架 UI 的特點

      • 簡潔

        Util UI 通常可以將復雜組件的 html 代碼量壓縮 3 - 10 倍,從而使項目的可維護性大幅提升.

        下面以查詢表單為例進行對比.

        先看效果演示.

        Util UI 的標簽使用 TagHelper 進行封裝 ,代碼如下.

        <util-card borderless="true" class="searchForm">
            <util-search-form label-width="120">
                <util-row gutter="24">
                    <util-column>
                        <util-input id="code" name="code"  ng-model="queryParam.code" label-text="identity.application.code"/>
                    </util-column>
                    <util-column>
                        <util-input id="name" name="name"  ng-model="queryParam.name" label-text="identity.application.name"/>
                    </util-column>
                    <util-column>
                        <util-select id="enabled" name="enabled"  ng-model="queryParam.enabled" label-text="identity.application.enabled"/>
                    </util-column>
                    <util-column>
                        <util-input id="remark" name="remark"  ng-model="queryParam.remark" label-text="identity.application.remark"/>
                    </util-column>
                    <util-column>
                    <util-column>
                    <util-range-picker id="begin_creation_time" name="begin_creation_time"  
                        label-text="util.beginCreationTime"
                        begin-date="queryParam.beginCreationTime" end-date="queryParam.endCreationTime"/>
                    </util-column>
                    <util-column>
                        <util-range-picker id="begin_last_modification_time" name="begin_last_modification_time"
                            label-text="util.beginLastModificationTime"
                            begin-date="queryParam.beginLastModificationTime" end-date="queryParam.endLastModificationTime" />
                    </util-column>
                    <util-column class="mb-md">
                        <util-flex justify="FlexEnd" align="Center" gap="Small">
                            <util-button id="btnRefresh" icon="Sync" on-click="refresh(btnRefresh)" text-reset="true"></util-button>
                            <util-button id="btnQuery" type="Primary" icon="Search" on-click="query(btnQuery)" text-query="true"></util-button>                        
                            <util-a is-search="true" class="ml-sm"></util-a>
                        </util-flex>
                    </util-column>
                </util-row>
            </util-search-form>
        </util-card>
        

        上面的標簽會轉換成 Ng Zorro 原生的 html 標簽.

        <nz-card class="searchForm" [nzBorderless]="true">
            <form nz-form="">
                <div nz-row="" [nzGutter]="24">
                    <div nz-col="" [nzLg]="8" [nzMd]="12" [nzSm]="24" [nzXl]="8" [nzXs]="24" [nzXXl]="6">
                        <nz-form-item>
                            <nz-form-label style="width:120px">{{'identity.application.code'|i18n}}</nz-form-label>
                            <nz-form-control>
                                <nz-input-group [nzSuffix]="tmp_code">
                                    <input #code="" #model_code="ngModel" name="code" nz-input="" [(ngModel)]="queryParam.code" />
                                </nz-input-group>
                                <ng-template #tmp_code="">
                                    <i (click)="model_code.reset()" *ngIf="model_code.value" class="ant-input-clear-icon"
                                        nz-icon="" nzTheme="fill" nzType="close-circle">
                                    </i>
                                </ng-template>
                            </nz-form-control>
                        </nz-form-item>
                    </div>
                    <div nz-col="" [nzLg]="8" [nzMd]="12" [nzSm]="24" [nzXl]="8" [nzXs]="24" [nzXXl]="6">
                        <nz-form-item>
                            <nz-form-label style="width:120px">{{'identity.application.name'|i18n}}</nz-form-label>
                            <nz-form-control>
                                <nz-input-group [nzSuffix]="tmp_name">
                                    <input #model_name="ngModel" #name="" name="name" nz-input="" [(ngModel)]="queryParam.name" />
                                </nz-input-group>
                                <ng-template #tmp_name="">
                                    <i (click)="model_name.reset()" *ngIf="model_name.value" class="ant-input-clear-icon"
                                        nz-icon="" nzTheme="fill" nzType="close-circle">
                                    </i>
                                </ng-template>
                            </nz-form-control>
                        </nz-form-item>
                    </div>
                    <div nz-col="" [nzLg]="8" [nzMd]="12" [nzSm]="24" [nzXl]="8" [nzXs]="24" [nzXXl]="6">
                        <nz-form-item>
                            <nz-form-label style="width:120px">{{'identity.application.enabled'|i18n}}</nz-form-label>
                            <nz-form-control>
                                <nz-select #enabled="" #x_enabled="xSelectExtend" name="enabled" x-select-extend="" [(ngModel)]="queryParam.enabled">
                                    <nz-option [nzLabel]="'util.defaultOptionText'|i18n"></nz-option>
                                    <ng-container *ngIf="!x_enabled.isGroup">
                                        <nz-option *ngFor="let item of x_enabled.options" [nzDisabled]="item.disabled" 
                                            [nzLabel]="item.text|i18n" [nzValue]="item.value">
                                        </nz-option>
                                    </ng-container>
                                    <ng-container *ngIf="x_enabled.isGroup">
                                        <nz-option-group *ngFor="let group of x_enabled.optionGroups" [nzLabel]="group.text|i18n">
                                            <nz-option *ngFor="let item of group.value" [nzDisabled]="item.disabled" 
                                                [nzLabel]="item.text|i18n" [nzValue]="item.value">
                                            </nz-option>
                                        </nz-option-group>
                                    </ng-container>
                                </nz-select>
                            </nz-form-control>
                        </nz-form-item>
                    </div>
                    <div *ngIf="expand" nz-col="" [nzLg]="8" [nzMd]="12" [nzSm]="24" [nzXl]="8" [nzXs]="24" [nzXXl]="6">
                        <nz-form-item>
                            <nz-form-label style="width:120px">{{'identity.application.remark'|i18n}}</nz-form-label>
                            <nz-form-control>
                                <nz-input-group [nzSuffix]="tmp_remark">
                                    <input #model_remark="ngModel" #remark="" name="remark" nz-input="" [(ngModel)]="queryParam.remark" />
                                </nz-input-group>
                                <ng-template #tmp_remark="">
                                    <i (click)="model_remark.reset()" *ngIf="model_remark.value" class="ant-input-clear-icon"
                                        nz-icon="" nzTheme="fill" nzType="close-circle">
                                    </i>
                                </ng-template>
                            </nz-form-control>
                        </nz-form-item>
                    </div>
                    <div *ngIf="expand" nz-col="" [nzLg]="8" [nzMd]="12" [nzSm]="24" [nzXl]="8" [nzXs]="24" [nzXXl]="6">
                        <nz-form-item>
                            <nz-form-label style="width:120px">{{'util.beginCreationTime'|i18n}}</nz-form-label>
                            <nz-form-control>
                                <nz-range-picker #begin_creation_time="" #x_begin_creation_time="xRangePickerExtend" 
                                    name="begin_creation_time" x-range-picker-extend="" 
                                    [(beginDate)]="queryParam.beginCreationTime" [(endDate)]="queryParam.endCreationTime" 
                                    [(ngModel)]="x_begin_creation_time.rangeDates">
                                </nz-range-picker>
                            </nz-form-control>
                        </nz-form-item>
                    </div>
                    <div *ngIf="expand" nz-col="" [nzLg]="8" [nzMd]="12" [nzSm]="24" [nzXl]="8" [nzXs]="24" [nzXXl]="6">
                        <nz-form-item>
                            <nz-form-label style="width:120px">{{'util.beginLastModificationTime'|i18n}}</nz-form-label>
                            <nz-form-control>
                                <nz-range-picker #begin_last_modification_time="" #x_begin_last_modification_time="xRangePickerExtend" 
                                    name="begin_last_modification_time" x-range-picker-extend="" 
                                    [(beginDate)]="queryParam.beginLastModificationTime" [(endDate)]="queryParam.endLastModificationTime" 
                                    [(ngModel)]="x_begin_last_modification_time.rangeDates">
                                </nz-range-picker>
                            </nz-form-control>
                        </nz-form-item>
                    </div>            
                    <div class="mb-md" nz-col="" [nzLg]="{span:expand?24:24}" [nzMd]="{span:expand?24:12}" [nzSm]="24" [nzXl]="{span:expand?24:24}" 
                        [nzXs]="24" [nzXXl]="{span:expand?12:6}">
                        <div nz-flex="" nzAlign="center" nzGap="small" nzJustify="flex-end">
                            <button #btnRefresh="" (click)="refresh(btnRefresh)" nz-button="" type="button">
                                <i nz-icon="" nzType="sync"></i>
                                {{'util.reset'|i18n}}
                            </button>
                            <button #btnQuery="" (click)="query(btnQuery)" nz-button="" nzType="primary" type="button">
                                <i nz-icon="" nzType="search"></i>
                                {{'util.query'|i18n}}
                            </button>
                            <a (click)="expand=!expand" class="ml-sm">
                                {{expand?('util.collapse'|i18n):('util.expand'|i18n)}}
                                <i nz-icon="" [nzType]="expand?'up':'down'"></i>
                            </a>
                        </div>
                    </div>
                </div>
            </form>
        </nz-card>
        

        <util-search-form> 是 Util UI 的查詢表單標簽.

        查詢表單支持響應式,并將按鈕區(qū)域始終放置在最后一行的右側.

        label-width 是一個擴展的范圍設置屬性, 為每個表單組件的 <nz-form-label> 設置 style="width:120px" 樣式, 避免了分別設置每個組件的寬度.

        Ng Zorro 表單組件由 <nz-form-item> , <nz-form-label> , <nz-form-control> 組合而成.

        <util-input> 和 <util-select> 設置了 label-text , 這是一個擴展屬性,它會激活 <nz-form-item> 結構的自動創(chuàng)建.

        <util-input> 是文本框, 除了為它自動創(chuàng)建 <nz-form-item> 結構, 還會添加清除內(nèi)容的功能.

        Util UI 大多常用組件的顯示文本會自動添加 i18n 管道, 比如 'identity.application.code'|i18n ,用于支持多語言.

        從前面的示例可以看到 Util UI 可以大幅提升 html 標簽的書寫效率, 降低維護成本.

      • 易用

        Util 對常用功能進行了高度封裝, 并提供簡單易用的 API.

        易用性是 Util UI 封裝的關鍵目標,也是 Util UI 存在的意義.

        本文后續(xù)將以最近更新的一個關鍵功能 - 表格設置, 演示易用性.

      • 強類型提示

        Util UI 提供的標簽使用 TagHelper 技術封裝, 支持強類型提示.

        如果你使用 Vs Code 開發(fā), Util UI 標簽提示信息大致與 Ng Zorro Vs Code 插件提示效果相當.

        Vs Code 的標簽提示信息并不精準, 包含很多與 html 相關的屬性, 比如 aria- 打頭的屬性就占了幾屏, 這降低了代碼提示的作用.

        如果使用 Vs 開發(fā), 甚至安裝了 Resharper , 代碼提示就能達到最佳效果.

      • 持續(xù)更新和改進

        Util UI 不僅僅是對 Ng Zorro 功能的簡單包裝, 更提供了常用功能的擴展.

        Util UI 擴展功能來自之前使用其它 UI 框架的經(jīng)驗, 另外收集項目開發(fā)時的實際需求,并加以整理,以滿足使用 Util UI 的項目.

        Util 團隊傾聽開發(fā)人員的心聲, 并持續(xù)改進, 從而更好的滿足項目需求.

      Util 應用框架 UI 的封裝實現(xiàn)方式

      • 使用 .cshtml 替代 .html 頁面.

        .cshtml 是 .Net 提供的一種高級 html 封裝技術.

        Util 創(chuàng)造性的將 .cshtml 引入 Angular 應用開發(fā).

        Util 將 cshtml 頁面作為 html 抽象層, 用來隱藏 html 的復雜性.

        Ng Zorro 組件庫定義了大量的 Angular 組件.

        使用 Angular 組件, 就是在 html 頁面中書寫自定義的標簽.

        Util 應用框架使用 TagHelper 對 Ng Zorro 標簽進行封裝, 以提供更加簡潔的用法.

        TagHelper 是一種 .Net 標簽, 在 .cshtml 文件中使用.

        雖然 TagHelper 標簽看上去也是一些自定義標簽 , 但它們不是 Angular 組件.

        Util 會在開發(fā)階段將 .cshtml 文件轉換成 html.

      • 使用 Angular 指令進行擴展.

        Ng Zorro 組件庫與 EasyUI 這樣的組件庫具有顯著差異.

        Ng Zorro 組件庫提供的 API 具有粒度細, 擴展性強的特點.

        Ng Zorro 組件的很多功能并不內(nèi)置于組件中,而是通過 Demo 的形式告訴你怎么使用.

        這為你提供了很大的靈活性和自由.

        但也意味著,如果你不加封裝,直接在項目中復制使用, 就會造成大量的冗余代碼, 降低項目的可維護性.

        要擴展 Ng Zorro 組件, 僅使用 TagHelper 封裝 html 是不夠的, 還需要找到編寫腳本的地方.

        封裝和擴展 Ng Zorro 組件, 通常有兩種方式.

        • 一種方式是創(chuàng)建新的 Angular 組件對原始組件進行包裝.

          使用組件包裝, 可以提供更加易用的 Api.

          不過這種封裝方式也有一些缺陷.

          • 新組件的 API 與原始組件可能不同, 增加了學習成本.

          • 由于需要將原始組件的 API 暴露出來 , 導致更多的冗余代碼.

          • 擴展性降低.

            對于表格這樣復雜的組件, html 結構相當復雜, 使用組件包裝通常不會保留原有的 html 結構.

            擴展點完全由新組件控制, 從而降低擴展性.

        • 另一種方式是使用 Angular 指令對原始組件進行擴展.

          Angular 指令使用起來就像標簽上的屬性一樣.

          使用 Angular 指令進行擴展, 最大優(yōu)勢是保留原始組件的全部用法, 不會降低其擴展性.

          當然指令封裝方式也帶來了新的挑戰(zhàn),那就是 html 標簽會更加復雜.

          Util UI 使用 Angular 指令進行封裝擴展, 并使用 TagHelper 標簽來隱藏 html 的復雜度.

      • Lambda表達式支持

        在 .cshtml 文件中使用 TagHelper 標簽, 你可以直接設置標簽上的屬性.

        不過 , 如果使用 .Net 開發(fā) API 后端, 并創(chuàng)建了 DTO 對象, 你可以將 DTO 屬性直接綁定到標簽上.

        下面演示查詢表單組件如何使用Lambda表達式綁定 DTO 屬性.

        DTO 代碼如下:

        /// <summary>
        /// 應用程序查詢參數(shù)
        /// </summary>
        public class ApplicationQuery : QueryParameter {
            /// <summary>
            /// 應用程序編碼
            ///</summary>
            [Description( "identity.application.code" )]
            public string Code { get; set; }
            /// <summary>
            /// 應用程序名稱
            ///</summary>
            [Description( "identity.application.name" )]
            public string Name { get; set; }
            /// <summary>
            /// 啟用
            ///</summary>
            [Description( "identity.application.enabled" )]
            public bool? Enabled { get; set; }
            /// <summary>
            /// 備注
            ///</summary>
            [Description( "identity.application.remark" )]
            public string Remark { get; set; }
            /// <summary>
            /// 起始創(chuàng)建時間
            /// </summary>
            [Display( Name = "util.beginCreationTime" )]
            public DateTime? BeginCreationTime { get; set; }
            /// <summary>
            /// 結束創(chuàng)建時間
            /// </summary>
            [Display( Name = "util.endCreationTime" )]
            public DateTime? EndCreationTime { get; set; }
            /// <summary>
            /// 起始最后修改時間
            /// </summary>
            [Display( Name = "util.beginLastModificationTime" )]
            public DateTime? BeginLastModificationTime { get; set; }
            /// <summary>
            /// 結束最后修改時間
            /// </summary>
            [Display( Name = "util.endLastModificationTime" )]
            public DateTime? EndLastModificationTime { get; set; }
        }
        

        .cshtml 代碼如下:

        @model ApplicationQuery
        
        <util-card borderless="true" class="searchForm">
            <util-search-form label-width="120">
                <util-row gutter="24">
                    <util-column>
                        <util-input for="Code" />
                    </util-column>
                    <util-column>
                        <util-input for="Name" />
                    </util-column>
                    <util-column>
                        <util-select for="Enabled" />
                    </util-column>
                    <util-column>
                        <util-input for="Remark" />
                    </util-column>
                    <util-column>
                        <util-range-picker for-begin="BeginCreationTime" for-end="EndCreationTime" />
                    </util-column>
                    <util-column>
                        <util-range-picker for-begin="BeginLastModificationTime" for-end="EndLastModificationTime" />
                    </util-column>
                    <util-column class="mb-md" md="24">
                        <util-flex justify="FlexEnd" align="Center" gap="Small">
                            <util-button id="btnRefresh" icon="Sync" on-click="refresh(btnRefresh)" text-reset="true"></util-button>
                            <util-button id="btnQuery" type="Primary" icon="Search" on-click="query(btnQuery)" text-query="true"></util-button>
                            <util-button icon="CheckSquare" on-click="container.masterToggle()" text-select-all="true" ng-if="!container.isMasterChecked()"></util-button>
                            <util-button icon="CloseSquare" on-click="container.masterToggle()" text-deselect-all="true" ng-if="container.isMasterChecked()"></util-button>
                            <util-a is-search="true" class="ml-sm"></util-a>
                        </util-flex>
                    </util-column>
                </util-row>
            </util-search-form>
        </util-card>
        

        Lambda表達式會讀取 DTO 對象的元數(shù)據(jù), 并自動設置常用屬性, 從而再次大幅提升生產(chǎn)力.

      Util 應用框架 UI 的組成

      • Util.Ui.NgZorro

        Util.Ui.NgZorro 類庫包含 Ng Zorro TagHelper 標簽, 目前已封裝官方正式發(fā)布的全部組件.

      • Util.Ui.NgAlain

        Util.Ui.NgAlain 類庫包含 Ng Alain 部分組件 TagHelper 標簽.

      • util-angular

        util-angular 是一個 typescript 腳本庫, 包含 Ng Zorro 擴展指令和常用操作 Helper.

      Util 應用框架 UI 最新進展

      Util 應用框架 UI 最近進行了全面改進,并取得了重大突破.

      最大的進展有2點, 一是開發(fā)機制的改進, 二是增加了表格設置功能.

      • 開發(fā)機制改進

        • 架構缺陷

          Util 應用框架將 .cshtml 文件引入 Angular 已有相當長的年頭.

          由于這種非主流的用法并沒有微軟官方的支持,所以一直存在相當多的問題.

          • 最主要的影響是導致開發(fā)階段運行緩慢.

            之前的開發(fā)流程, Angular 組件在開發(fā)階段直接訪問 cshtml 頁面,所以開發(fā)階段必須使用 Angular JIT 模式, 它比 Angular AOT 模式要慢一些.

            cshtml 在第一次訪問時, 尚未創(chuàng)建緩存 , 會比較慢.

            Angular 應用啟動時,將訪問根模塊引用的所有頁面, 所以啟動時會產(chǎn)生相當?shù)目D.

            這個問題通過 Angular 延遲加載模塊得到緩解.

            如果項目比較大,包含數(shù)十個業(yè)務模塊, 將每個業(yè)務模塊創(chuàng)建為延遲加載模塊.

            當應用啟動時, 并不會訪問所有頁面, 只有請求了某個業(yè)務模塊的功能, 才會訪問該模塊包含的 cshtml 頁面.

            不過從 Angular 13 開始, Angular 移除了傳統(tǒng)的視圖引擎, 導致上述開發(fā)方式無法使用延遲加載模塊.

            這意味著所有業(yè)務模塊在開發(fā)階段必須在根模塊中引用.

            Angular 應用啟動后將訪問所有 cshtml 頁面, 這顯然是不可接受的.

            一種可行的解決辦法是使用微前端方案.

            微前端架構將業(yè)務模塊分離到不同的項目從而減少應用啟動時間.

            一些較大的項目和團隊使用微前端架構是合適的.

            但微前端架構具有復雜性, 使用微前端架構代替延遲加載模塊則非常牽強.

            這是 Util 團隊進行全面改造的根本原因.

          • 另一個影響是項目結構比較復雜.

            Util 采用的項目結構最早來自 .Net Core Angular 項目模板, 并加以修改.

            Angular 應用被放在 ClientApp 目錄中.

            .cshtml 文件則被放在 Pages 目錄中.

            這導致組件與模板的對應關系比較復雜.

        • 改進方案

          很多時候, 解決問題最重要是思路的轉變.

          之前的架構缺陷主要來自在開發(fā)階段讓 Angular 組件直接請求 cshtml 頁面,從而與原生 Angular 應用產(chǎn)生差別.

          不過, Util 使用 cshtml 僅限于開發(fā)階段, 發(fā)布之后實際上與 cshtml 沒有任何關系.

          cshtml 的作用只是幫助生成 html 而已.

          現(xiàn)代化開發(fā)一個重要的功能是熱更新, 比如 Angular 應用, 它會持續(xù)監(jiān)視你的相關文件.

          當你編輯完 .ts 或 .html 文件時, 瀏覽器就會自動刷新.

          如果我們監(jiān)視所有 .cshtml 文件,并在保存 cshtml 文件時自動生成對應的 html 文件,就能從根本上解決問題.

          由于只需要處理保存的 cshtml 文件, 生成 html 的速度將非常迅速.

          當 html 生成完成, 后續(xù)流程則與原生 angular 應用相同, 從而解決引入 cshtml 相關的所有缺陷.

          現(xiàn)在, 編輯并保存 .cshtml 文件, 瀏覽器就會自動刷新, 與原生 Angular 應用相比, 大致慢幾百毫秒, 通常可以忽略不計.

          項目結構復雜的問題則很好解決, 將 .cshtml 與 Angular 組件放在一起即可.

          這與原生 Angular 應用相似, 只需修改 .cshtml 生成 html 文件的路徑規(guī)則.

          一直以來, Util UI的架構比較臃腫, 只能在 Vs 中開發(fā).

          但現(xiàn)在前端基本都使用 Vs Code.

          最新 UI 架構與原生 Angular 應用差別很小, 同樣適合使用 Vs Code 開發(fā).

          下面是使用 Vs Code 打開的項目結構.

      • 表格設置

        表格是業(yè)務系統(tǒng)的基石.

        我們收集了一些項目上使用 Ng Zorro 表格的反饋意見.

        • 當表格列較多時,如果不進行寬度設置, 則會顯示得很畸形.

          要解決這個問題, 需要設置表格 nzScroll 屬性的 x 值.

          nzScroll 的 x 可以讓表格產(chǎn)生橫向的滾動條, 從而將表格內(nèi)容拉伸.

          不過這個值應該設置成多少合適, 則是一門學問.

          通常需要計算表格中有多少列,每列大致占多少寬度, nzScroll.x 的值大致是這些寬度之和.

          手工計算寬度費時費力, 最好是能自動計算.

        • 另一個問題是凍結表格頭, 并讓表格在一定高度滾動.

          通過設置 nzScroll 屬性的 y 值可以做到這一點.

          不過設置 nzScroll.y 也是一門學問, 因為不同屏幕大小可能需要設置不同的值,在開發(fā)階段很難固定.

          一些公司使用某些方法計算以達到自適應高度,不過大多針對比較固定的頁面布局,且相對簡單.

          更好的辦法是讓用戶在運行時根據(jù)自己的要求動態(tài)更新.

        • 除了表格的總寬度, 每個列的寬度設置也是一個頭痛的問題.

          列寬大多與內(nèi)容相關, 在開發(fā)階段設置固定列寬, 當內(nèi)容超過固定寬度就會出現(xiàn)換行,影響美觀.

          如果在開發(fā)階段設置一個默認寬度, 并在運行時可由用戶修改就能解決問題.

          當然最好能支持拖動表頭修改列寬, 則更為方便.

        • 自定義列是很多項目的必備功能.

          當表格列非常多, 用戶希望只顯示其中感興趣的一部分列, 并能修改列的顯示順序.

          Ng Zorro 支持自定義列功能, 不過使用起來比較復雜.

          當你啟用了自定義列, 用來固定左右側的 nzLeft 和 nzRight 就變得不那么利索.

          列與列之間經(jīng)常會出現(xiàn)一些縫隙或對不齊的現(xiàn)象, Ng Zorro 官方文檔給出了一些調(diào)整建議, 不過也是非常麻煩.

        • 諸如表格批量編輯,表格行編輯, 樹形異步加載等需求都是很早之前就已經(jīng)擴展支持, 就不在此一一列出.

        下面介紹 Util UI 表格設置功能.

        先來一個表格設置的效果圖.

        可以看到, 它確實解決了前面提到的棘手問題.

        如何開啟表格設置功能?

        表格標簽示例代碼.

        @*表格*@
        <util-table id="tb" key="identity_operation" enable-table-settings="true"
                    show-checkbox="true" show-line-number="true" 
                    url="operation" query-param="queryParam" sort="SortId">
            <util-td for="Name"></util-td>
            <util-td for="Uri"></util-td>
            <util-td for="IsBase" sort="false"></util-td>
            <util-td for="Remark"></util-td>
            <util-td for="Enabled">
                <util-tag color-type="GeekBlue" ng-if="row.enabled" text-enabled="true"></util-tag>
                <util-tag color-type="Red" ng-if="!row.enabled" text-not-enabled="true"></util-tag>
            </util-td>
            <util-td for="CreationTime"></util-td>
            <util-td for="LastModificationTime"></util-td>
            <util-td title-operation="true">
                <util-a on-click="openDetailDialog(row)" text-detail="true"></util-a>
                <util-container acl="operation.update">
                    <util-divider type="Vertical"></util-divider>
                    <util-a on-click="openEditDrawer(row)" text-update="true"></util-a>
                </util-container>
                <util-container acl="operation.delete">
                    <util-divider type="Vertical"></util-divider>
                    <util-a danger="true" on-click="delete(row.id)" text-delete="true"></util-a>
                </util-container>
            </util-td>
        </util-table>
        

        要開啟表格設置功能, 只需要在 <util-table> 標簽設置 enable-table-settings 屬性為 true.

        你可能要問, 需要編寫 ts 腳本代碼嗎?

        不用 !!!

        如果你看過 Ng Zorro 官方自定義列的示例, 知道需要將一個 NzCustomColumn[] 對象傳入 <nz-table>的 nzCustomColumn 屬性.

        那么, Util UI 的自定義列功能是否使用 Ng Zorro 官方的實現(xiàn)呢?

        下面來看看生成的 html , 答案就會揭曉.

        <nz-table #tb="" #x_tb="xTableExtend" (nzPageIndexChange)="x_tb.pageIndexChange($event)"
            (nzPageSizeChange)="x_tb.pageSizeChange($event)" order="SortId" url="operation" x-table-extend=""
            [(nzPageIndex)]="x_tb.queryParam.page" [(nzPageSize)]="x_tb.queryParam.pageSize" [(queryParam)]="queryParam"
            [nzBordered]="ts_tb.bordered" [nzCustomColumn]="ts_tb.columns" [nzData]="x_tb.dataSource"
            [nzFrontPagination]="false" [nzLoading]="x_tb.loading" [nzPageSizeOptions]="x_tb.pageSizeOptions"
            [nzScroll]="ts_tb.scroll" [nzShowQuickJumper]="true" [nzShowSizeChanger]="true" [nzShowTotal]="total_tb"
            [nzSize]="ts_tb.size" [nzTotal]="x_tb.total">
            <thead>
                <tr>
                    <th (nzCheckedChange)="x_tb.masterToggle()" nzCellControl="util.checkbox"
                        [nzChecked]="x_tb.isMasterChecked()" [nzDisabled]="!x_tb.dataSource.length"
                        [nzIndeterminate]="x_tb.isMasterIndeterminate()" [nzLeft]="ts_tb.isLeft('util.checkbox')"
                        [nzRight]="ts_tb.isRight('util.checkbox')" [nzShowCheckbox]="true"
                        [titleAlign]="ts_tb.getTitleAlign('util.checkbox')">
                    </th>
                    <th nzCellControl="util.lineNumber" [nzLeft]="ts_tb.isLeft('util.lineNumber')"
                        [nzRight]="ts_tb.isRight('util.lineNumber')" [titleAlign]="ts_tb.getTitleAlign('util.lineNumber')">
                        {{'util.lineNumber'|i18n}}
                    </th>
                    <th (nzResizeEnd)="ts_tb.handleResize($event,'identity.operation.name')"
                        (nzSortOrderChange)="x_tb.sortChange('name',$event)" nz-resizable="" nzBounds="window"
                        nzCellControl="identity.operation.name" nzPreview="" [nzLeft]="ts_tb.isLeft('identity.operation.name')"
                        [nzRight]="ts_tb.isRight('identity.operation.name')" [nzShowSort]="true" [nzSortFn]="true"
                        [titleAlign]="ts_tb.getTitleAlign('identity.operation.name')">
                        {{'identity.operation.name'|i18n}}
                        <nz-resize-handle nzDirection="right"></nz-resize-handle>
                    </th>
                    <th (nzResizeEnd)="ts_tb.handleResize($event,'identity.operation.uri')"
                        (nzSortOrderChange)="x_tb.sortChange('uri',$event)" nz-resizable="" nzBounds="window"
                        nzCellControl="identity.operation.uri" nzPreview="" [nzLeft]="ts_tb.isLeft('identity.operation.uri')"
                        [nzRight]="ts_tb.isRight('identity.operation.uri')" [nzShowSort]="true" [nzSortFn]="true"
                        [titleAlign]="ts_tb.getTitleAlign('identity.operation.uri')">
                        {{'identity.operation.uri'|i18n}}
                        <nz-resize-handle nzDirection="right"></nz-resize-handle>
                    </th>
                    <th (nzResizeEnd)="ts_tb.handleResize($event,'identity.operation.isBase')" nz-resizable="" nzBounds="window"
                        nzCellControl="identity.operation.isBase" nzPreview=""
                        [nzLeft]="ts_tb.isLeft('identity.operation.isBase')"
                        [nzRight]="ts_tb.isRight('identity.operation.isBase')"
                        [titleAlign]="ts_tb.getTitleAlign('identity.operation.isBase')">
                        {{'identity.operation.isBase'|i18n}}
                        <nz-resize-handle nzDirection="right"></nz-resize-handle>
                    </th>
                    <th (nzResizeEnd)="ts_tb.handleResize($event,'identity.operation.remark')"
                        (nzSortOrderChange)="x_tb.sortChange('remark',$event)" nz-resizable="" nzBounds="window"
                        nzCellControl="identity.operation.remark" nzPreview=""
                        [nzLeft]="ts_tb.isLeft('identity.operation.remark')"
                        [nzRight]="ts_tb.isRight('identity.operation.remark')" [nzShowSort]="true" [nzSortFn]="true"
                        [titleAlign]="ts_tb.getTitleAlign('identity.operation.remark')">
                        {{'identity.operation.remark'|i18n}}
                        <nz-resize-handle nzDirection="right"></nz-resize-handle>
                    </th>
                    <th (nzResizeEnd)="ts_tb.handleResize($event,'identity.operation.enabled')"
                        (nzSortOrderChange)="x_tb.sortChange('enabled',$event)" nz-resizable="" nzBounds="window"
                        nzCellControl="identity.operation.enabled" nzPreview=""
                        [nzLeft]="ts_tb.isLeft('identity.operation.enabled')"
                        [nzRight]="ts_tb.isRight('identity.operation.enabled')" [nzShowSort]="true" [nzSortFn]="true"
                        [titleAlign]="ts_tb.getTitleAlign('identity.operation.enabled')">
                        {{'identity.operation.enabled'|i18n}}
                        <nz-resize-handle nzDirection="right"></nz-resize-handle>
                    </th>
                    <th (nzResizeEnd)="ts_tb.handleResize($event,'util.creationTime')"
                        (nzSortOrderChange)="x_tb.sortChange('creationTime',$event)" nz-resizable="" nzBounds="window"
                        nzCellControl="util.creationTime" nzPreview="" [nzLeft]="ts_tb.isLeft('util.creationTime')"
                        [nzRight]="ts_tb.isRight('util.creationTime')" [nzShowSort]="true" [nzSortFn]="true"
                        [titleAlign]="ts_tb.getTitleAlign('util.creationTime')">{{'util.creationTime'|i18n}}
                        <nz-resize-handle nzDirection="right"></nz-resize-handle>
                    </th>
                    <th (nzResizeEnd)="ts_tb.handleResize($event,'util.lastModificationTime')"
                        (nzSortOrderChange)="x_tb.sortChange('lastModificationTime',$event)" nz-resizable="" nzBounds="window"
                        nzCellControl="util.lastModificationTime" nzPreview=""
                        [nzLeft]="ts_tb.isLeft('util.lastModificationTime')"
                        [nzRight]="ts_tb.isRight('util.lastModificationTime')" [nzShowSort]="true" [nzSortFn]="true"
                        [titleAlign]="ts_tb.getTitleAlign('util.lastModificationTime')">
                        {{'util.lastModificationTime'|i18n}}
                        <nz-resize-handle nzDirection="right"></nz-resize-handle>
                    </th>
                    <th (nzResizeEnd)="ts_tb.handleResize($event,'util.operation')" nz-resizable="" nzBounds="window"
                        nzCellControl="util.operation" nzPreview="" [nzLeft]="ts_tb.isLeft('util.operation')"
                        [nzRight]="ts_tb.isRight('util.operation')" [titleAlign]="ts_tb.getTitleAlign('util.operation')">
                        {{'util.operation'|i18n}}
                        <nz-resize-handle nzDirection="right"></nz-resize-handle>
                    </th>
                </tr>
            </thead>
            <tbody>
                <tr *ngFor="let row of x_tb.dataSource;index as index">
                    <td (click)="$event.stopPropagation()" (nzCheckedChange)="x_tb.toggle(row)" nzCellControl="util.checkbox"
                        [nzAlign]="ts_tb.getAlign('util.checkbox')" [nzChecked]="x_tb.isChecked(row)"
                        [nzLeft]="ts_tb.isLeft('util.checkbox')" [nzRight]="ts_tb.isRight('util.checkbox')"
                        [nzShowCheckbox]="true">
                    </td>
                    <td nzCellControl="util.lineNumber" [nzAlign]="ts_tb.getAlign('util.lineNumber')"
                        [nzLeft]="ts_tb.isLeft('util.lineNumber')" [nzRight]="ts_tb.isRight('util.lineNumber')">
                        {{row.lineNumber}}
                    </td>
                    <td nzCellControl="identity.operation.name" [nzAlign]="ts_tb.getAlign('identity.operation.name')"
                        [nzEllipsis]="ts_tb.getEllipsis('identity.operation.name')"
                        [nzLeft]="ts_tb.isLeft('identity.operation.name')" [nzRight]="ts_tb.isRight('identity.operation.name')">
                        {{row.name}}
                    </td>
                    <td nzCellControl="identity.operation.uri" [nzAlign]="ts_tb.getAlign('identity.operation.uri')"
                        [nzEllipsis]="ts_tb.getEllipsis('identity.operation.uri')"
                        [nzLeft]="ts_tb.isLeft('identity.operation.uri')" [nzRight]="ts_tb.isRight('identity.operation.uri')">
                        {{row.uri}}
                    </td>
                    <td nzCellControl="identity.operation.isBase" [nzAlign]="ts_tb.getAlign('identity.operation.isBase')"
                        [nzEllipsis]="ts_tb.getEllipsis('identity.operation.isBase')"
                        [nzLeft]="ts_tb.isLeft('identity.operation.isBase')"
                        [nzRight]="ts_tb.isRight('identity.operation.isBase')">
                        <i *ngIf="!row.isBase" nz-icon nzType="close"></i>
                        <i *ngIf="row.isBase" nz-icon nzType="check"></i>
                    </td>
                    <td nzCellControl="identity.operation.remark" [nzAlign]="ts_tb.getAlign('identity.operation.remark')"
                        [nzEllipsis]="ts_tb.getEllipsis('identity.operation.remark')"
                        [nzLeft]="ts_tb.isLeft('identity.operation.remark')"
                        [nzRight]="ts_tb.isRight('identity.operation.remark')">
                        {{row.remark}}
                    </td>
                    <td nzCellControl="identity.operation.enabled" [nzAlign]="ts_tb.getAlign('identity.operation.enabled')"
                        [nzEllipsis]="ts_tb.getEllipsis('identity.operation.enabled')"
                        [nzLeft]="ts_tb.isLeft('identity.operation.enabled')"
                        [nzRight]="ts_tb.isRight('identity.operation.enabled')">
                        <nz-tag *ngIf="row.enabled" nzColor="geekblue">{{'util.enabled'|i18n}}</nz-tag>
                        <nz-tag *ngIf="!row.enabled" nzColor="red">{{'util.notEnabled'|i18n}}</nz-tag>
                    </td>
                    <td nzCellControl="util.creationTime" [nzAlign]="ts_tb.getAlign('util.creationTime')"
                        [nzEllipsis]="ts_tb.getEllipsis('util.creationTime')" [nzLeft]="ts_tb.isLeft('util.creationTime')"
                        [nzRight]="ts_tb.isRight('util.creationTime')">
                        {{row.creationTime|date:'yyyy-MM-dd HH:mm'}}
                    </td>
                    <td nzCellControl="util.lastModificationTime" [nzAlign]="ts_tb.getAlign('util.lastModificationTime')"
                        [nzEllipsis]="ts_tb.getEllipsis('util.lastModificationTime')"
                        [nzLeft]="ts_tb.isLeft('util.lastModificationTime')"
                        [nzRight]="ts_tb.isRight('util.lastModificationTime')">
                        {{row.lastModificationTime|date:'yyyy-MM-dd HH:mm'}}
                    </td>
                    <td nzCellControl="util.operation" [nzAlign]="ts_tb.getAlign('util.operation')"
                        [nzEllipsis]="ts_tb.getEllipsis('util.operation')" [nzLeft]="ts_tb.isLeft('util.operation')"
                        [nzRight]="ts_tb.isRight('util.operation')">
                        <a (click)="openDetailDialog(row)">{{'util.detail'|i18n}}</a>
                        <ng-container *aclIf="'operation.update'">
                            <nz-divider nzType="vertical"></nz-divider>
                            <a (click)="openEditDrawer(row)">{{'util.update'|i18n}}</a>
                        </ng-container>
                        <ng-container *aclIf="'operation.delete'">
                            <nz-divider nzType="vertical"></nz-divider>
                            <a (click)="delete(row.id)" class="ant-btn-dangerous">{{'util.delete'|i18n}}</a>
                        </ng-container>
                    </td>
                </tr>
            </tbody>
        </nz-table>
        <ng-template #total_tb="" let-range="range" let-total="">
            {{ 'util.tableTotalTemplate'|i18n:{start:range[0],end:range[1],total:total} }}
        </ng-template>
        <x-table-settings #ts_tb=""
            key="identity_operation" [enableFixedColumn]="true"
            [initColumns]="[{'title':'util.checkbox','width':x_tb.config.table.checkboxWidth,'align':'left'},
            {'title':'util.lineNumber','width':x_tb.config.table.lineNumberWidth,'align':'left'},
            {'title':'identity.operation.name'},{'title':'identity.operation.uri'},
            {'title':'identity.operation.isBase'},{'title':'identity.operation.remark'},
            {'title':'identity.operation.enabled'},{'title':'util.creationTime'},
            {'title':'util.lastModificationTime'},{'title':'util.operation'}]">
        </x-table-settings>
        

        觀察 <nz-table> 標簽, 可以發(fā)現(xiàn) [nzCustomColumn]="ts_tb.columns" , 說明確實使用的是 Ng Zorro 官方提供的自定義列功能.

        生成的 html 比較復雜, enable-table-settings 除了開啟自定義列外,還會啟用拖動列寬等功能.

        前面提到, Util Ui 提供的標簽可以壓縮 3-10 倍的 html 代碼量 , 從這里可以看出, 絕非信口雌黃.

        <x-table-settings> 是由 util-angular 腳本庫提供的表格設置組件.

        <x-table-settings> 的 initColumns 屬性設置了一個列信息數(shù)組, 將列集合傳入表格設置組件.

        <x-table-settings> 組件經(jīng)過系列工序, 輸出 Ng Zorro 需要的自定義列信息.

        所以, 無需手工編寫任何 ts 腳本代碼, 即可完成相關功能.

        可以看到, TagHelper 不僅可以封裝 html 復雜度,甚至能為你生成一些簡單的 js 對象.

        要打開表格設置對話框, 需要一個按鈕.

        .cshtml 代碼如下.

        show-table-settings 用于顯示表格設置對話框, 傳入表格的引用變量名 tb.

        <util-a show-table-settings="tb"></util-a>
        

        生成的 html 如下.

        <a (click)="ts_tb.show()" nz-tooltip="" [nzTooltipTitle]="'util.tableSettings'|i18n">
            <i nz-icon="" nzType="setting"></i>
        </a>
        

        Util UI 的擴展指令和組件具有一些約定的命名.

        表格組件的引用變量名為 tb , 對應的表格設置組件則為 ts_tb .

        表格設置組件提供了一個 show() 函數(shù), 調(diào)用該函數(shù)即可打開表格設置窗口.

      總結

      本文分享了 Util 應用框架 UI 最近的突破與進展.

      Util 應用框架 UI 最新架構已經(jīng)穩(wěn)定, 可以放心使用.

      一些開發(fā)人員問到使用教程, 嗯, 這是個傷心事, Util 應用框架一直是心傳口授模式, 確實沒有.

      不過 Util 也在考慮突破原有的使用群體, 面向更大的范圍傳播.

      使用教程和文檔已經(jīng)在路上, 歡迎大家使用 , 我們將以更快的速度提供.

      posted @ 2024-04-28 12:31  何鎮(zhèn)汐  閱讀(1473)  評論(6)    收藏  舉報
      主站蜘蛛池模板: 亚洲人成网站18禁止| 毛片无码免费无码播放| 亚洲自在精品网久久一区| 免费观看又色又爽又黄的崩锅| 亚洲国产成人自拍视频网| 欧美白妞大战非洲大炮| 在线高清免费不卡全码| 亚洲 日韩 国产 制服 在线| 婷婷开心色四房播播| 黑人av无码一区| 40岁成熟女人牲交片20分钟| 国产精品一区二区三区自拍| 亚洲乱理伦片在线观看中字| 白丝乳交内射一二三区| 少妇宾馆粉嫩10p| 亚洲熟女乱综合一区二区三区| 国产成人午夜在线视频极速观看| 国产果冻豆传媒麻婆| 在线精品亚洲区一区二区| 日本深夜福利在线观看| 亚洲欧美综合精品二区| 国产精品区免费视频| 国产短视频一区二区三区| 黎城县| 国产AV影片麻豆精品传媒| 377P欧洲日本亚洲大胆| 中文字幕精品亚洲无线码二区| 在线观看中文字幕码国产| 亚洲AV日韩精品久久久久| 亚洲国产一区二区三区久| 午夜性爽视频男人的天堂| 下面一进一出好爽视频| 专干老肥熟女视频网站| 午夜视频免费试看| 日本老熟女一二三区视频| 亚洲色欲色欲大片www无码| 中国CHINA体内裑精亚洲日本| аⅴ天堂中文在线网| 亚洲第一人伊伊人色综合| 国产日韩欧美| 亚欧洲乱码视频一二三区|