gpt4 book ai didi

javascript - 如何根据参数设置微光组件的初始状态?

转载 作者:行者123 更新时间:2023-12-01 12:02:37 25 4
gpt4 key购买 nike

我正在努力弄清楚如何在微光组件层次结构中实现数据向下,向上操作(使用 Ember Octane,v3.15)。
我有一个带有项目列表的父组件。当用户单击 Parent 组件中的按钮时,我想用相关项目的数据填充 Editor 组件;当用户在 Editor 组件中单击“保存”时,将更改填充回父级。这是发生的事情:
GIF of my app
如何使文本框填充“Hello”,并在单击“保存”时将更改保留回上面的列表?
代码

{{!-- app/components/parent.hbs --}}
<ul>
{{#each this.models as |model|}}
<li>{{model.text}} <button {{on 'click' (fn this.edit model)}}>Edit</button></li>
{{/each}}
</ul>

<Editor @currentModel={{this.currentModel}} @save={{this.save}} />
// app/components/parent.js
import Component from '@glimmer/component';
export default class ParentComponent extends Component {
@tracked models = [
{ id: 1, text: 'Hello'},
{ id: 2, text: 'World'}
]
@tracked currentModel = null;

@action
edit(model) {
this.currentModel = model;
}

@action
save(model) {
// persist data
this.models = models.map( (m) => m.id == model.id ? model : m )
}
}
{{!-- app/components/editor.hbs --}}
{{#if @currentModel}}
<small>Editing ID: {{this.id}}</small>
{{/if}}
<Input @value={{this.text}} />
<button {{on 'click' this.save}}>Save</button>
// app/components/editor.hbs
import Component from '@glimmer/component';
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";

export default class EditorComponent extends Component {
@tracked text;
@tracked id;

constructor() {
super(...arguments)
if (this.args.currentModel) {
this.text = this.args.currentModel.text;
this.id = this.args.currentModel.id;
}

}

@action
save() {
// persist the updated model back to the parent
this.args.save({ id: this.id, text: this.text })
}
}
基本原理/问题
我决定将 Editor 实现为有状态组件,因为这似乎是从 <Input /> 组件中获取表单数据的最惯用方式。我使用 args 设置初始状态。由于 this.currentModel@tracked 中的 ParentComponent ,我希望重新分配该属性以更新传递给 @currentModel 的参数 Editor
确实情况似乎如此,因为单击 ParentComponent 中的一项旁边的“编辑”会使 <small>Editing ID: {{this.id}}</small> 出现。但是,既不会填充 <Input /> 元素的值,也不会填充 id 元素的值。
我知道 this.textthis.id 没有更新,因为当父级中的 constructor 更改时, EditorComponentcurrentModel 没有重新运行......但我坚持要做什么。

我试过的
当我试图弄清楚这一点时,我遇到了 this example ( code ),它在 BlogAuthorComponent ( hbs ) 和 BlogAuthorEditComponent ( hbs , js ) 之间具有几乎相同的交互。他们的解决方案,适用于我的问题,是这样编写 EditorComponent :
{{!-- app/components/editor.hbs --}}
{{#if this.isEditing}}
<small>Editing ID: {{@currentModel.id}}</small>
<Input @value={{@currentModel.text}} />
<button {{on 'click' this.save}}>Save</button>
{{/if}}
// app/components/editor.hbs
import Component from '@glimmer/component';
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";

export default class EditorComponent extends Component {
get isEditing() {
return !!this.args.currentModel
}

@action
save() {
// persist the updated model back to the parent
this.args.save({ id: this.id, text: this.text })
}
}
enter image description here
有用!但我不喜欢这个解决方案,有几个原因:
  • 将传递给子组件的某物的属性修改为 arg 似乎......令人毛骨悚然......老实说,我不确定它为什么会起作用(因为虽然 ParentComponent#models@tracked ,但我不希望其中的 POJO 的属性要遵循的数组...)
  • 这会在您键入时更新 ParentComponent 中的文本,虽然简洁,但不是我想要的——我希望只有在用户单击“保存”时才保留更改(在这种情况下什么都不做)
  • 在我的真实应用程序中,当用户没有“编辑”现有项目时,我希望表单是“添加项目”表单,单击“保存”按钮会添加一个新项目。我不确定如何在不复制表单和/或对 <Input @value ...
  • 中发生的内容做一些逻辑处理的情况下做到这一点

    我也遇到了 this question ,但它似乎指的是旧版本的微光。
    感谢您阅读这篇文章---我将不胜感激任何建议!

    最佳答案

    跟踪对 currentModel 的更改在您的 editor组件并设置默认值,使用 get访问者:

    get model() {
    return this.args.currentModel || { text: '', id: null };
    }

    在您的模板中执行以下操作:
    {{#if this.model.id}}
    <small>
    Editing ID:
    {{this.model.id}}
    </small>
    {{/if}}
    <Input @value={{this.model.text}} />
    <button type="button" {{on "click" this.save}}>
    Save
    </button>

    但请注意,这将改变 currentModel在您的 parent组件,我猜这不是你想要的。为了避免这种情况,请从您正在编辑的模型的属性中创建一个新对象。

    解决方案:
    // editor/component.js
    export default class EditorComponent extends Component {
    get model() {
    return this.args.currentModel;
    }

    @action
    save() {
    this.args.save(this.model);
    }
    }

    在您的父组件中,从传递的模型创建一个新对象。另外,记得重置 currentModel在保存 Action 中。现在您可以检查是否 id在您的 parent 中是否为空组件的 save行动,如果是,只需执行您的 save逻辑:
    // parent/component.js
    @tracked currentModel = {};

    @action
    edit(model) {
    // create a new object
    this.currentModel = { ...model };
    }

    @action
    save(model) {
    if (model.id) {
    this.models = this.models.map((m) => (m.id == model.id ? model : m));
    } else {
    // save logic
    }

    this.currentModel = {};
    }

    关于javascript - 如何根据参数设置微光组件的初始状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60246130/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com