【问题标题】:View Not Updating Immediately From Service with element.classList.add()使用 element.classList.add() 查看不立即从服务更新
【发布时间】:2020-05-22 20:15:39
【问题描述】:

我正在向服务中的元素添加css 类,但更改不会立即发生。更改大约需要一秒钟来更新视图。我需要立即进行更改,不得拖延。我已经尝试过 ApplicaionRef 并在服务中调用 this.applicationRef.tick(),但这不起作用。我尝试在 NgZone 的this.zone.run 中运行该服务的方法,但也没有成功。

@Component({
  selector: 'calling',
  templateUrl: './calling.component.html',
  styleUrls: ['./calling.component.scss']
})
export class CallingComponent {
 constructor(private hidingService: HidingService) {}

 callHide() {
  this.hidingService.hide();
 }
}
@Injectable({
  providedIn: 'root'
})
export class HidingService {
 constructor() {}

 hide() {
  const elements = document.querySelectorAll('.hideable-field');
  elements.forEach(element => {
    element.classList.add('hide');
  });
 }
}

这是 styles.css 中的 CSS(可从所有组件访问)以供参考,但这部分正在运行。添加这个“隐藏”类会隐藏带有这个 CSS 的字段:

.hideable-field {
  &.hide {
    visibility: hidden !important;
  }
}

如果我在组件中使用这个隐藏逻辑,它就可以工作。这些字段会立即隐藏。如果我在服务中使用这个隐藏的逻辑,则需要一点时间。

【问题讨论】:

  • 不确定服务与组件的滞后。但您可能想要更新您的逻辑并使用 renderer2 this.renderer.addClass(this.el.nativeElement, className); 使其更具角度。同样对于这样的操作,我更喜欢对元素使用指令而不是使用 querySelectorAll 来查找元素。它更干净、更有棱角。
  • 可能有很多元素具有.hideable-field 类并且迭代forEach 中的所有元素可能是导致此延迟的原因。

标签: javascript html css angular


【解决方案1】:

让服务进行直接影响组件 HTML 的更改通常是一种反模式。在 Angular 中使用文档查询选择器也不是一个好主意。但是,如果您想让某些东西快速运行,请尝试在您的服务中为 hide 函数设置一个超时:

 hide() {
  setTimeout(() => {
    const elements = document.querySelectorAll('.hideable-field');
    elements.forEach(element => {
      element.classList.add('hide');
    });
  }, 0)
 }

更正确的方法是在每个对象上都有一个布尔值 isHidden 属性。然后,在您的模板中,您可以使用[hidden]*ngIf 有条件地显示它们。请参阅Angular2: conditional display, bind to [hidden] property vs. *ngIf directive,了解两种方法之间的差异。使用*ngIf 的示例:

组件模板中的某处:

<ng-container *ngFor='let element of myElements'>
  <div class='my-element' *ngIf='!element.isHidden'></div>
</ng-container>

组件中的新隐藏功能:

 hide() {
   this.myElements.forEach(element => element.isHidden = true);
 }

【讨论】:

    【解决方案2】:

    解决方案原来是在返回之前等待 UI 更新。有一个名为 requestAnimationFrame() 的方法允许您执行此操作。

    export class HidingService {
     constructor() {}
    
     hide(): Observable<{}> {
      const elements = document.querySelectorAll('.hideable-field');
      elements.forEach(element => {
        element.classList.add('hide');
      });
    
      const subject = new Subject();
      requestAnimationFrame( () => {
        // Fields will hide in this frame
        requestAnimationFrame( () => {
          // Fields are hidden
          subject.next(); 
        });
      });
      return subject.pipe();
     }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-15
      • 1970-01-01
      • 2020-12-07
      • 2018-11-08
      • 1970-01-01
      相关资源
      最近更新 更多