实施操纵Dom的第三方库的正确方法是什么?

时间:2018-12-31 18:02:52

标签: angular angular2-directives angular-renderer2

我正在使用第3方库将小部件呈现到屏幕上(Okta的SignInWidget)。窗口小部件的呈现方式如下:

this.oktaSignInWidget.renderEl(
    { el: '#widget-container' },
    () => {},
    err => {
      console.error(err);
    }
  );

我最初的想法是将其放入指令中,但是即使使用指令,您也应该让Renderer2进行渲染。这里有最佳实践吗?

1 个答案:

答案 0 :(得分:6)

由于小部件可能替换/构建了给定容器的内容,因此这似乎是常规Angular组件的经典用例。 似乎您也不需要动态实例化(通常可在3rd party库包含教程中找到)。

如果使用选择器myapp-login创建一个组件,则可以将其放置在某些登录页面中:

<h1>Login</h1>
<p>Hi people, login to get more features:</p>
<myapp-login></myapp-login>

大致遵循this Angular University's article about @ViewChild(也简要提到了第三方库),this SO answer或Netanel Basal的文章Using 3rd Party Library Inside Angular2(省略输入),我们可以进行如下操作:

要访问自定义组件中的元素,应让Angular通过添加用#container装饰的ElementRef类型的属性来注入对标记有@ViewChild('container')的元素的引用。 / p>

@ViewChild('container')
container: ElementRef;

在组件的构造函数中,您可以构造小部件实例。

初始化视图后,应让小部件实例将其自身呈现到容器元素中。记住要在销毁组件时销毁小部件(也许通过调用.remove())。

这是您登录组件的未经测试的骨架:

...
import OktaSignIn from '@okta/okta-signin-widget';
import '@okta/okta-signin-widget/dist/css/okta-sign-in.min.css';
import '@okta/okta-signin-widget/dist/css/okta-theme.css';

@Component({
  selector: 'myapp-login',
  template: '<div #container></div>'
})
export class Login implements AfterViewInit, OnDestroy {
  @ViewChild('container')
  container: ElementRef;

  oktaSignInWidget: OktaSignIn;

  constructor() {
    this.oktaSignInWidget = new OktaSignIn({baseUrl: 'https://{yourOktaDomain}'});
  }

  ngAfterViewInit() {
    const containerElem = this.container.nativeElement;
    this.oktaSignInWidget.renderEl(
      { el: containerElem },
      response => {}, // success callback
      error => {} // error callback 
    );
  }

  ngOnDestroy() {
    if (this.oktaSignInWidget) {
      this.oktaSignInWidget.remove();
      this.oktaSignInWidget = null;
    }
  }
}

您应将域的基本配置和其他特定于环境的数据移动到特殊文件(environment.ts),例如here

如果尝试登录后发生任何有意义的事情,则应创建一个服务来处理身份验证状态,并将(转换后的)结果委托给它。