【问题标题】:emberjs child component not re-rendering after property update属性更新后,emberjs 子组件未重新渲染
【发布时间】:2020-07-18 16:16:17
【问题描述】:

我有一个页面组件(五个为什么),其中包含多个输入,用户可以选择这些输入来完成输入。当用户点击 finalize 时,所有问题都将被禁用。

页面组件

五个为什么.hbs:

{{#each this.whys as |why i|}}
  <Generic::RichTextInput
    @value={{why.content}}
    @onChange={{action this.whyChanged i}}
    @disabled={{this.isFinalized}} />
{{/each}}
<button {{on "click" this.finalizeWhy}}>Finalize</button>

五个为什么.ts

interface AnalyzeFiveWhysArgs {
  dataStory: DataStory;
}

export default class AnalyzeFiveWhys extends Component<AnalyzeFiveWhysArgs> {
  @alias("args.dataStory.fiveWhysAnalysis") fiveWhysAnalysis

  @tracked
  isFinalized: boolean = this.fiveWhysAnalysis.isFinalized ?? false;

  @tracked
  whys: LocalWhy[] = this.fiveWhysAnalysis.whys;

  @tracked
  isFinalized: boolean = this.fiveWhysAnalysis.isFinalized ?? false; 

  @action
  async finalizeWhy() {
    this.isFinalized = true;
  }

当我的富文本组件只是一个常规文本区域时,这可以正常工作。但是,我正在尝试实现 tinymce,这需要我在 Embers 小安全魔法空间之外做一些事情。

我的富文本组件:

模板:

<textarea id={{this.id}} disabled={{this.templatePieceIsDisabled}}>{{@value}}</textarea>

打字稿:

interface GenericRichTextInputArgs {
  value?: string;
  onChange: (value: string) => void;
  name: string;
  disabled?: boolean;
}

export default class GenericRichTextInput extends Component<GenericRichTextInputArgs> {
  constructor(owner: unknown, args: GenericRichTextInputArgs) {
    super(owner, args);

    this.initializeTinymce();
  }

  id = this.args.name;

  get editor() {
    return tinymce.get(this.id);
  }

  get settings() {
    console.log(this.args.disabled);

    const settings: TinyMCESettings = {
      selector: `#${this.id}`,
      setup: (editor: Editor) => this.setupEditor(this, editor),
      readonly: this.args.disabled ? this.args.disabled : false
    };
    return settings;
  }

  initializeTinymce() {
    Ember.run.schedule('afterRender', () => {
      console.log("re-initializing"); // I expect to see this log every time the isFinalized property in the five-whys component changes. But I only see it on page load.

      tinymce.init(this.settings);
    });
  }

  setupEditor(self: GenericRichTextInput, editor: Editor) {
    ... // details of tinymce API
  }
}

当我点击finalize按钮时,富文本组件中disabled标志的效果没有改变。

注意:

我使用的 tinymce 库将文本区域显示设置为无,将 aria-hidden 设置为 true。这是因为它将文本区域包装在一个小部件中。所以我必须使用库的api来设置禁用。

【问题讨论】:

    标签: ember.js ember-components glimmer.js


    【解决方案1】:

    我想通了。 Ember 不会为更新生命周期事件运行构造函数。所以我需要告诉 Ember 在重新渲染模板时重新运行初始化程序。我必须使用https://github.com/emberjs/ember-render-modifiers 来执行此操作。

    所以我的富文本编辑器模板看起来像:

    <textarea
      id={{this.id}}
      {{did-update this.updateDisabled @disabled}}>
      {{@value}}
    </textarea>
    

    我在富文本编辑器后面的代码中添加了这个动作:

      @action
      updateDisabled(element: HTMLTextAreaElement, [disabled]: any[]) {
        this.disabled = disabled;
    
        this.editor.destroy();
        this.initializeTinymce();
      }
    

    【讨论】: