0

我已经简化了我遇到的 lit 问题。我的组件的某些状态保存在一个对象中。我希望能够通过一些精细的控制来检测子属性的变化并做出反应。这是示例:

import { html, LitElement } from "lit";
import { customElement, state } from "lit/decorators.js";

@customElement("my-app")
export class App extends LitElement {
    @state({
    hasChanged(newVal: any, oldVal: any) {
      console.log(`[hasChanged] new fruit is: ${newVal?.fruit}`);
      console.log(`[hasChanged] old fruit is: ${oldVal?.fruit}`);
      return true;
    }})
    data = {
        fruit: "apples",
        weather: "rain",
    };

    constructor() {
        super();
        setTimeout(() => {
            this.data.fruit = "bananas";
            this.data = { ...this.data };
        }, 3000);

        setTimeout(() => {
            this.data.weather = "snow";
            this.data = { ...this.data };
        }, 6000);
    }

    render() {
        return html`
            Weather: ${this.data.weather} Fruit: ${this.data.fruit}
        `;
    }

    shouldUpdate(changedProperties: any) {
        // I only want to update if the weather is changing, not the fruit
       console.log(
            `new weather is: ${changedProperties.get("data")?.weather}`
        );
        console.log(`current weather is: ${this.data.weather}`);
        console.log(`new fruit is: ${changedProperties.get("data")?.fruit}`);
        console.log(`current fruit is: ${this.data.fruit}`);
        console.log("");

        if (changedProperties.get("data")?.weather !== this.data.weather) {
            return true;
        } else {
            return false;
        }
    }
}

当 shouldUpdate 触发时,组件对子属性值的评估已经更新。所以我无法比较changedProperties.get("data")?.weatherthis.data.weather是否已经改变。

[更新] 根据 michaPau 的建议,我研究了该hasChanged方法 - 不幸的是,当触发更改时,这也会返回相同的 oldVal 和 newVal 值。

有谁知道新方法或修复?如果我将该状态对象拆分为两个单独的状态变量,它会按预期工作,但对象和属性在保持代码可读性方面效果要好得多。在我看来,将超过 4 或 5 个属性传递到组件中开始变得混乱。

4

1 回答 1

0

我不确切知道你做错了什么,但你的代码似乎确实有效,但是正如其他人提到的那样,你应该将扩展运算符与赋值操作一起使用:

<script type="module">
import {
  LitElement,
  html,
  css
} from "https://unpkg.com/lit-element/lit-element.js?module";

class MyContainer extends LitElement {
  static get styles() {
    return css`
      .wrapper {
        min-height: 100px;
        min-width: 50%;
        margin: 5em;
        margin-top: 0;
        padding: 10px;
        background-color: lightblue;
      }
    `;
  }

  render() {
    return html`
      <div class="wrapper">
        <slot></slot>
      </div>
    `;
  }
}

class MyItem extends LitElement {
  static properties = {
    data: {
      state: true,
      hasChanged: (newVal, oldVal) => {
        console.log(`[hasChanged] new fruit is: ${newVal?.fruit}`);
        console.log(`[hasChanged] old fruit is: ${oldVal?.fruit}`);
        return true;
      }
    }
  };

  constructor() {
    super();
    this.data = {
      fruit: "apples",
      weather: "rain"
    };
   
    setTimeout(() => {
      this.data = { ...this.data, fruit: 'bananas' };
    }, 3000);

    setTimeout(() => {
      this.data = { ...this.data, weather: "snow" };
    }, 6000);
  }

  render() {
    return html`
    <div style="background-color: ${this.getBackgroundColor()}">
      Weather: ${this.data.weather} Fruit: ${this.data.fruit}
    </div>
    `;
  }

  getBackgroundColor() {
    if(this.data.weather === 'snow') return 'white';
    else if(this.data.fruit === 'bananas') return 'yellow';
    return 'blue';
  }
  
  shouldUpdate(changedProperties) {
    // I only want to update if the weather is changing, not the fruit
    console.log(`new weather is: ${changedProperties.get("data")?.weather}`);
    console.log(`current weather is: ${this.data.weather}`);
    console.log(`new fruit is: ${changedProperties.get("data")?.fruit}`);
    console.log(`current fruit is: ${this.data.fruit}`);
    console.log("");

    if (changedProperties.get("data")?.weather !== this.data.weather) {
      return true;
    } else {
      return false;
    }
  }
}

customElements.define("my-container", MyContainer);
customElements.define("my-item", MyItem);

</script>

<my-container>
  <my-item></my-item>
</my-container>

如果您还想查看更改yellowshouldUpdate 函数中的代码以在changedProperties.get("data")未定义的情况下返回 true 的更改。

于 2022-01-12T10:57:08.823 回答