更新元素 属性 绑定

Update elements property binding

我有一个基于 LitElement 的 Web 组件,它呈现一个 mdw-dialog,里面有一个自定义元素,该元素使用来自父组件的 属性。当用户单击 a 按钮时,将显示呈现几个输入字段的对话框。这一切都很好,但我希望在显示对话框之前单击按钮时将 属性 重置为空对象,尽管我可以轻松地这样做 - 它似乎对对话框元素。

父元素

export class PageApplications extends LitElement {

    static get properties() {
        return {
            application: { type: Object }
        }
    }

    constructor() {
        super();
        this.application = {};
    }

    onMouseOver(event) {
        this.shadowRoot.querySelector('mwc-fab').extended = ('mouseenter' === event.type);
    }

    openDialog() {
        console.log('PageApplication.openDialog:', this.application);
        this.application = {};
        let dialog = this.shadowRoot.querySelector('mwc-dialog');
        dialog.requestUpdate;
        dialog.open = true;
    }

    closedDialog(event) {
        console.log('closedDialog:', this.application)
        if ('ok' === event.detail.action) {
            // NOP
        }
    }

    render() {
        console.log('PageApplication.render', this.application);
        return html`
            <style type="text/css">
                mwc-fab {
                    position: fixed;
                    right: 1rem;
                }
                mwc-list {
                    background-color: #FFF;
                }
            </style>
            <mwc-fab showIconAtEnd icon="add_circle" label="New Application" 
                @mouseenter="${this.onMouseOver}"
                @mouseout="${this.onMouseOver}"
                @click="${this.openDialog}"
                >
            </mwc-fab>
            <mwc-dialog heading="Create Application"
                @closed="${this.closedDialog}">
                <cnvy-create-application
                    .application="${this.application}"
                ></cnvy-create-application>
                <mwc-button
                    slot="primaryAction"
                    dialogAction="ok"
                >Create</mwc-button>
                <mwc-button
                    slot="secondaryAction"
                    dialogAction="cancel"
                >Cancel</mwc-button>            
            </mwc-dialog>
            <h2>Applications</h2>

如您所见,应用程序 属性 绑定到元素 cnvy-create-application

export class ConvoyCreateApplication extends LitElement {

    constructor() {
        super();
    }

    static get properties() {
        return {
            application: { type: Object }
        }
    }

    render() {
        console.log('ConvoyCreateApplication.render', this.application);
        return html`
            <style>
                mwc-formfield {
                    display: block;
                }
            </style>
            <mwc-formfield>
                <mwc-textfield 
                    placeholder="Name" 
                    helper="Name of application"
                    .value="${this.application.name}"
                    @change="${e => this.application.name = e.target.value}"
                    ></mwc-textfield>
            </mwc-formfield>
            <mwc-formfield>
                <mwc-textarea 
                    rows="2" 
                    placeholder="Description" 
                    helper="Short description"
                    .value="${this.application.description}"
                    @change="${e => this.application.description = e.target.value}"
                ></mwc-textfield>
            </mwc-formfield>
        `;
    }

}
customElements.define('cnvy-create-application', ConvoyCreateApplication);

问题是 - 我第一次单击按钮时,对话框按预期显示,每个文本字段显示 "undefined",这可能没问题,因为道具未在空对象中定义。 我分别输入值 "a" 和 "b" 并在对话框和控制台打印中单击确定

closedDialog: {name: "a", description: "b"}

符合预期。如果我再次单击按钮,"application" 属性 应重置为空对象,但 UI 显示带有 "a" 和 "b" 的文本字段,如果我更改 "b"到"d",只有"d"发回

closedDialog: {description: "d"}

意思是应用程序对象实际上被重置为空,但是显示的不是这个……所以,我该如何触发更新?我尝试了各种"update"、"requestUpdate" ..和这样的生命周期方法但无济于事..

mwc-textfield 在内部使用本机 input 并将 value 属性 绑定传递给它。这是 属性 从多个来源更新的情况之一(编辑文本时来自 .value="${this.application.name}" 和 DOM)。在这种情况下,lit-html 可能不知道如何更新值,并可能导致数据与实际显示的内容不一致。要解决这个问题,您可以使用 live directive:it

checks binding value against the live DOM value, instead of the previously bound value, when determining whether to update the value.

import {live} from 'lit-html/directives/live';

// ...

render() {
  return html`
    <mwc-textfield
      .value=${live(this.application.name)}
               ^^^^
    ></mwc-textfield>
  `;
}

openDialog() 中,您可能错过了 dialog.requestUpdate˅; 中的括号,尽管没有必要调用它:this.application = {}; 足以触发更新。

要防止文本字段显示 undefined,您可以在绑定中提供备用值

<mwc-textfield
  .value=${live(this.application.name || '')}
></mwc-textfield>

或者用空值初始化整个数据结构:

constructor() {
  this.application = {
    a: '',
    b: '',
    // ...
  };
}