【问题标题】:Update elements property binding更新元素属性绑定
【发布时间】:2020-04-16 16:47:15
【问题描述】:

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

父元素

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);

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

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

正如预期的那样。如果我然后再次单击按钮,“应用程序”属性应重置为空对象,但 UI 显示带有“a”和“b”的文本字段,如果我将“b”更改为“d”,则只发回“d”

closedDialog: {description: "d"}

意味着应用程序对象实际上被重置为空,但是这不是显示的内容......那么,我该如何触发更新?我尝试了各种“更新”、“请求更新”.. 和这样的生命周期方法,但无济于事..

【问题讨论】:

    标签: polymer lit-element


    【解决方案1】:

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

    根据 live DOM 值检查绑定值,而不是之前的 绑定值,判断是否更新值时。

    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: '',
        // ...
      };
    }
    

    【讨论】:

    • 非常感谢@Umbo - 这确实解决了我的问题,添加了实时指令/功能......很棒的东西! :)
    • 很高兴我能帮上忙! :)
    猜你喜欢
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 2012-07-18
    • 1970-01-01
    • 2015-08-30
    • 2017-11-09
    • 2012-04-29
    相关资源
    最近更新 更多