首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >LitElement维护内部状态

LitElement维护内部状态
EN

Stack Overflow用户
提问于 2020-06-26 19:56:09
回答 1查看 271关注 0票数 0

我正在尝试用LitElement构建一个图表。图表从用户获取数据属性,并显示此数据(图表图)。它还从数据中获取系列名称,以便为每个系列显示一个带有复选框的图例,这些复选框可用于在图表绘图上显示或隐藏该系列的数据。

下面是一个非常小的示例,其中图表图只是包含数据点(3,5,4,7)的div,而图例只是复选框。预期的行为是,当复选框被选中/取消选中时,图表图(data Div)中的相应数据将被显示/隐藏。例如,最初默认选中这两个复选框,并且两个系列的数据都正确显示。但是,如果我取消选中第一个复选框,我希望隐藏"series1“的数据,因此只显示5和7。

正是这种复选框行为让我无法正常工作。当我选中或取消选中某个复选框时,我将看似已正确更新的this.series记入日志,反映选中了哪些复选框,但图表图(data Div)未更新。

代码语言:javascript
运行
复制
import { LitElement, css, html } from "lit-element";
import { render } from "lit-html";

class TestElement extends LitElement {
  static get properties() {
    return {
      data: { type: Array },
      series: { type: Array },
    };
  }

  constructor() {
    super();
    this.data = [];
    this.series = [];
  }
  checkboxChange(e) {
    const inputs = Array.from(this.shadowRoot.querySelectorAll("input")).map(n => n.checked);
    this.series = this.series.map((s, i) => ({ ...s, checked: inputs[i] }));
    console.log("this.series", this.series);
  }
  render() {
    this.series = Object.keys(this.data[0]).map(key => ({ key, checked: true }));
    const data = this.data.map(d => this.series.map(s => (s.checked ? html`<div>${d[s.key]}</div>` : "")));
    const series = this.series.map(
      s => html`<input type="checkbox" ?checked=${s.checked} @change=${this.checkboxChange} />`
    );
    return html`${data}${series}`;
  }
}
customElements.define("test-element", TestElement);

render(
  html`<test-element
    .data=${[
      { series1: "3", series2: "5" },
      { series1: "4", series2: "7" },
    ]}
  ></test-element>`,
  window.document.body
);
EN

回答 1

Stack Overflow用户

发布于 2021-04-18 02:13:55

尝试以下操作:

代码语言:javascript
运行
复制
import { LitElement, html } from 'lit-element';

class TestElement extends LitElement {
  static get properties() {
    return {
      data: { attribute: false, accessors: false },
      series: { attribute: false, accessors: false },
      checked: { attribute: false, accessors: false },
    };
  }

  constructor() {
    super();
    this.data = [];
    this.series = new Map();
    this.checked = new Map();
  }

  get data() {
    return this.__data || [];
  }

  set data(v) {
    const oldValue = this.__data;
    this.__data = Array.isArray(v) ? v : [];
    this.series = new Map();

    for (const row of this.data) {
      for (const [series, value] of Object.entries(row)) {
        this.series.set(series, [...this.series.get(series) || [], value])
      }
    }

    for (const series of this.series.keys()) {
      this.checked.set(series, this.checked.get(series) ?? true);
    }

    this.requestUpdate('data', oldValue);
    this.requestUpdate('series', null);
    this.requestUpdate('checked', null);
  }

  checkboxChange(e) {
    this.checked.set(e.target.dataset.series, e.target.checked);
    this.requestUpdate('checked', null);
  }

  render() {
    return [
      [...this.series.entries()].map(([series, values]) => values.map(value => html`
        <div ?hidden="${!this.checked.get(series)}">${value}</div>
      `)),
      [...this.checked.entries()].map(([series, checked]) => html`
        <input type="checkbox" ?checked=${checked} data-series="${series}" @change=${this.checkboxChange} />
      `)
    ];
  }
}

customElements.define("test-element", TestElement);

现场示例:https://webcomponents.dev/edit/FEbG9UA3nBMqtk9fwQrD/src/index.js

此解决方案提供了一些改进:

  1. 在数据更新时缓存序列和选中状态,而不是在每个呈现属性时使用hidden attr隐藏未选中的序列
  2. 使用data-attributes将集合项上的可序列化数据传递到event attributes attribute: false而不是type: Array (假设您不需要从属性反序列化D13。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62594225

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档