html - 将自己的 ui 组件提取到一个地方

标签 html css angular

我正在学习angular,因此我对bootstrapng-bootstrap 都不感兴趣,因为学习目的我想自己做所有事情。

我创建了一个简单的下拉菜单。我的目标是将它放在一个地方并在许多不同的组件中使用,但我想尽可能避免代码重复。

我有的是:

  • 类文件
    export class DropdownElement {
      private _currentValue: string;
      private _listContent: string[];
      private _unrolled: boolean;

      //constructor with getters/setter ommitted for brevity
    }

  • 在使用该下拉列表的组件中
    @Component({
      selector: 'app-users',
      templateUrl: './users.component.html',
      styleUrls: ['./users.component.scss']
    })
    export class UsersComponent implements OnInit {

      private userTypeDropdown: DropdownElement;

      constructor() {
        this.userTypeDropdown = new DropdownElement('Select a type', [
          {
            name: 'Admin'
          },
          {
            name: 'Guest'
          }
        ], false);
      }

      private dropdownClicked(dropdownElement: DropdownElement): void {
        dropdownElement.open = !dropdownElement.open;
      }

      private dropdownEntryClicked(dropdownEntry: string, dropdown: DropdownElement): void {
        dropdown.currentValue = dropdownEntry;
      }

      private closeDropdown(event: Event, dropdown: DropdownElement): void {
        dropdown.open = false;
      }
    }
  • 内部模板文件
    <div class="dropdown-box" (clickOutside)="closeDropdown($event, userTypeDropdown)">
      <div class="dropdown-btn-box">
        <button type="button" class="dropdown-btn-with-label"
                (click)="dropdownBtnClicked(userTypeDropdown)">
          {{userTypeDropdown.currentValue}}
        </button>
        <button type="button" class="caret-down-btn" (click)="dropdownClicked(userTypeDropdown)">
          <i class="fas fa-caret-down"></i>
        </button>
      </div>
      <ul class="dropdown-ul" *ngIf="userTypeDropdown.unrolled">
        <li *ngFor="let listEntry of userTypeDropdown.listContent" class="dropdown-list-entry"
            (click)="dropdownEntryClicked(listEntry, userTypeDropdown)">
          {{listEntry.currentValue}}
        </li>
      </ul>
    </div>
  • .scss 为简洁起见省略了文件

我想把它放在一个地方(以避免代码重复)并在不同的组件中使用。

我会怎么做。 我相信这正是 ng-bootstrap 所做的。他们从 bootstrap 中获取下拉列表,将其包装在一些逻辑中,使其成为一个指令,仅此而已。我认为这里的答案是作为指令或子组件实现的(但不确定 @Input/@Output 是否是该目的的正确选择)。再次,正如我所说,我是初学者,所以我可能是错的,所以这个问题。

这里“将下拉定义保留在一个地方并在许多地方使用”的正确方法是什么?

最佳答案

您可以为所有这些可重用组件创建一个模块,例如下拉菜单、模式甚至 HTML 输入控件,这些控件可以将您的验证和功能封装在它们所拥有的基线功能之上。 您可以进一步将独立于框架的代码抽象成更多的类,然后只使用 Angular 进行查看。就像您将代码抽象到 Dropdown 元素类中一样,您可以拥有一个提供 View 的基本下拉组件,这是您使用应用程序用户实现的。您可以通过在单独的组件中取出下拉 View 来使其更易于重用,这样做将帮助您在需要下拉列表的所有此类用例中使用下拉元素。您只需为下拉元素提供初始化数据和初始值,就可以开始了。

  • DropDown 类和可重用组件

    export class Dropdown {
      private _currentValue: string;
      private _listContent: string[];
      private _unrolled: boolean;
    
      //constructor with getters/setter ommitted for brevity
    }
    
    @Component({
      selector: 'drop-down',
      templateUrl: './drop-down.component.html',
      styleUrls: ['./drop-down.component.scss']
    })
    export class DropDownComponent extends Dropdown implements OnInit {
      // Input are a way to of communication from parent to child as parent feeds the child with input properties
      // you can have your setter here
      @Input('list-content')
      public listContent : Array<any>;
      @Input('current-value')
      currentValue: any;
      // Output events are just a way of child to parent communication
      @Output('on-select-item')
      onSelectItem : EventEmitter<any> = new EventEmitter();
    
      constructor() {}
    
      public dropdownClicked(): void {
        this.open = !this.open;
      }
    
      public dropdownEntryClicked(dropdownEntry: string): void {
        this.currentValue = dropdownEntry;
        this.onSelectItem.emit(this.currentValue);  
      }
    
      public closeDropdown(): void {
        this.open = false;
      }
    }
    
  • 使用此 Dropdown 可重用组件的应用程序用户 考虑到您是初学者,让我们将它们放在同一模块中,以便 App-users 与 DropdownComponent 出现在同一模块中。 (稍后您可以将下拉列表移动到 SharedModule 并通过在包含 AppUsersComponent 的模块中导入 SharedModule 来使用它)

    @Component({
      selector: 'app-users',
      templateUrl: './users.component.html',
      styleUrls: ['./users.component.scss']
    })
    export class UsersComponent implements OnInit {
    
     public userTypeDropdown: Array<any>;
     public defaultUserType = { name: 'Guest'};
     public selectedUserType: any;
    
     constructor() {
         this.userTypeDropdown = ['Select a type',
           {
             name: 'Admin'
           },
           {
             name: 'Guest'
           }
        ];
     }
      public onSelectUser (userTypeSelected : any) : void {
         this.selectedUserType = userTypeSelected;
      }
    }
    
  • 下拉菜单模板将与您用于应用程序用户的模板相同,但有一些变化,即函数参数(因为我已经改变了一些)

  • App-user 组件的模板主要亮点

<drop-down [list-content]="userTypeDropdown"
[current-value]="defaultUserType"
(on-select-item)="onSelectUser(userTypeSelected)></drop-down>

希望这对您有所帮助!

关于html - 将自己的 ui 组件提取到一个地方,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56742892/

相关文章:

javascript - 在 AngularJS 中为按钮添加默认值

html - 使 flex div 的宽度适应内容,但将 Flex 元素放在单独的行中

angular - 使用切片管道后如何连接字符串

Angular 6 单元测试 http 获取请求

html - 垂直下拉导航问题

html - 侧边栏在某些页面中移至底部但在其他页面中完美

html - Bootstrap 表单中的阵容标签和复选框

angular - ngModel 不显示该值

javascript - 使用javascript在html5中获取日期值

javascript - 在选择时更改文本区域的边框颜色