前端analysis | 3w & 1h

《angular8》- angular 组件升级引用ui-grid最佳实践

2020-06-10

Angular web 项目少不了列表的存在。针对angularjs web项目,进行技术升级,需要耗费一番功夫,不是简单的从ng-if变为*ngIf就能完成的。这些Angular框架,都替我们考虑到了。本文重点主要介绍UpgradeComponent进行组件升级,包裹使用angularjs ui-grid,实现angular 列表ui 保持不变效果。替代方案ag-grid,请移步ag-grid具体参考
介于代码不方便copy,只能使用官网example进行实践过程介绍,下面我们进入主题:

技术要点

  • 本文实践依据angularjs component api,本文angularjs组件如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # 不是所有的都可以进行升级的哦,
    export const heroGrid = {
    bindings: {
    hero: '<',
    deleted: '&'
    },
    template: `
    <h2>{{$ctrl.hero.name}} details!</h2>
    <div><label>id: </label>{{$ctrl.hero.id}}</div>
    <button ng-click="$ctrl.onDelete()">Delete</button>
    `,
    controller: function() {
    this.onDelete = () => {
    this.deleted(this.hero);
    };
    }
    };
  • 不是所有的angularjs指令都可以升级,在angular组件中使用哦,具体请参考(https://angular.io/guide/upgrade#using-component-directives)

  • angularjs vs angular属性绑定

  • angular指令的input、output与angularjs的输入、输出对应

升级实践

定义angularjs组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
export const heroGrid = {
bindings: {
gridOptions: '<',
deleted: '&'
},
template: `
<div id="grid1" ui-grid="gridOptions" class="grid"></div>
`,
controller: function() {
this.onDelete = () => {
this.deleted(this.hero);
};
}
};

定义angular8 directive

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { Directive, ElementRef, Injector, Input, Output, EventEmitter } from '@angular/core';
import { UpgradeComponent } from '@angular/upgrade/static';
import { Hero } from '../hero';

@Directive({
selector: 'hero-grid'
})
export class heroGridDirective extends UpgradeComponent {
private subject:Subject = new Subject();
@Input() gridOptions: any;

@Input()
set gridData(data:Hero[]){
if(!data){
return;
}
this.gridOptions.data = data;
this.subject.next();
};

@Output() deleted: EventEmitter<Hero>;

constructor(elementRef: ElementRef, injector: Injector) {
super('heroGrid', elementRef, injector);
const $scope = injector.get('scope');
this.subject.subscribe(res => {
//延迟更新当前scope
defer(() => {
$scope.digest();
});
});
}
}
  • 需要扩展UpgradeComponent组件
  • 需要调用super方法,传递参数给angularjs组件
  • 上面例子,heroGrid,是angularjs中注册的组件的名称。

ngModule中声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@NgModule({
imports: [
BrowserModule,
UpgradeModule
],
declarations: [
heroGridDirective,
/* . . . */
]
})
export class AppModule {
constructor(private upgrade: UpgradeModule) { }
ngDoBootstrap() {
this.upgrade.bootstrap(document.body, ['heroApp'], { strictDi: true });
}
}

定义外层容器html,使用directive

  • ContainerComponent 需要在appModule declaration中定义
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    import { Component } from '@angular/core';
    import { Hero } from '../hero';

    @Component({
    selector: 'my-container',
    template: `
    <h1>Tour of Heroes</h1>
    <hero-grid [gridOptions]="gridOptions" [gridData]="heroList"
    (deleted)="heroDeleted($event)">
    </hero-grid>
    `
    })
    export class ContainerComponent {
    heroList = [
    new Hero(1, 'Windstorm'),
    new Hero(2, 'Storm'),
    ];
    heroDeleted(hero: Hero) {
    hero.name = 'Ex-' + hero.name;
    },
    gridOptions = {
    useExternalSorting: true,
    data:this.heroList,
    columnDefs: [
    { name: 'name' },
    { name: 'gender' },
    { name: 'company', enableSorting: false}
    ],
    onRegisterApi: function( gridApi ) {
    $scope.gridApi = gridApi;
    $scope.gridApi.core.on.sortChanged( $scope, $scope.sortChanged );
    $scope.sortChanged($scope.gridApi.grid, [ $scope.gridOptions.columnDefs[1] ] );
    }
    };
    }

    问题:

  • 表格在没有数据的时候,需要展示表头,然后存在数据了,需要渲染出来?
  • 如果表格渲染出来后,如果存在,折叠展开,那么折叠的也要展示,怎么办?
  • 会不会存在,js 数据更新了,但是界面ui不刷新问题?

解答

  • 首先肯定需要传递gridOptions,不然表头无法渲染
  • 新数据过来了,需要再次渲染;基于angular []数据会动态更新,我们理论上更新gridOptions即可,介于已有代码,修改浮动大,我们引入gridData,监听数据变化,set方法每次操作,顺带修改optioins,然后通过subject,通知optons一变动,digest更新angularjs
  • 如果数据渲染,此时还需要变化怎么? 遇到的问题,就是digest没有收到数据更新,此时解决办法是使用loading,loading = false,渲染数据,loading = true,展示laoding,这样,数据会对应的更新。

更多推荐

参考

使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏