【问题标题】:Implementing a dynamic Time Zone selector Angular 2/4/5实现动态时区选择器 Angular 2/4/5
【发布时间】:2017-11-11 08:31:46
【问题描述】:

我需要在我的 Angular 4/5 应用程序中构建一个 TimeZone 选择器。当用户更改时区时,我希望页面上显示的所有时间值都会立即更新。

我打算使用:

  • momentjs 使用 angular2-momentangular-moment-timezone 支持时区。
  • 要格式化日期,请使用amLocal 管道,然后是其他管道。
  • 当用户选择不同的时区时,我打算拨打moment.tz.setDefault(_timezone)

从此时起,上述值被格式化为新时区,而当前显示的时间值不会改变。角度变化检测机制不会更新显示的时间值,因为输入值没有改变。

由于性能开销(考虑到时区更改不是频繁活动),我不想创建“不纯”管道。

作为后备,我可以创建一个将当前时区作为参数的管道(或使用现有的管道)。它确实有效,但我需要将当前时区值传递给每个组件和模板。

我无法找到一种方法让 Angular 更改检测相信即使值没有更改也有更改。

欢迎提出任何建议。

【问题讨论】:

  • 我无法找到一种方法让 Angular 更改检测相信即使值没有更改也会发生更改:是的,你有:这被称为不纯的管道。
  • 双绑定可能是您的最佳选择?
  • 当您说“不更新显示的时间值”时,精确是什么意思?您是否只是表示这些值代表“现在”并且您希望它们像时钟一样向前移动?如果是这样,您需要某种计时器。

标签: angular timezone momentjs angular2-moment


【解决方案1】:

管道不是组件(很明显),它们没有自己的变化检测机制,除了pure 标志。所以有两种方法可以达到预期的效果:

  1. 使用智能不纯管道,它将跟踪以前的值和以前的格式化结果。 Angular 的AsyncPipe(实际上是不纯的,如果有另一种方法可以做到这一点,那么我相信它会变得纯正)是这样实现的:

    if (value !== this.value || this.timeZoneChanged) 
    {
        this.value = value;
        this.formattedValue = ... render value ...;
    }
    return this.formattedValue;
    

    您可以在github上浏览AsyncPipe源代码。

  2. 使用自定义组件呈现日期,即自定义ControlValueAccessor

【讨论】:

    【解决方案2】:

    当使用例如ngx-translate 时,切换语言意味着获取新的翻译。如您所见here 他们使用不纯的管道,正如您所说,这意味着性能问题。

    我想的另一种方法是定义一个组件DateComponent 可用于您的整个应用程序。这样,您将拥有<custom-date [date]="new Date()"></custom-date>,而不是在您的html 中{{ value | formatDate }}

    在您的自定义日期组件中将如下所示

    @Component({
      selector: 'custom-date',
      template: '<span>{{ formatedDate }}</span>'
    })
    export class DateComponent {
      @Input() date: string;
      timezone: string;
      formatedDate: string;
      constructor(private userService: UserService) {}
    
      ngOnInit(){
        this.timezone = this.userService.getTimeZone();
        this.updateValue();
        this.userService.onTimezoneChange()
          .subscribe(timezone => {
            this.timezone = timezone;
            this.updateValue();
          });
      }
    
      updateValue() {
        // Do your formatting the way you want
        this.formatedDate = moment(this.date).tz(this.timezone).format();
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-25
      • 1970-01-01
      • 2018-09-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多