web - 属性更改时点亮的 Web 组件未更新

标签 web components shadow-dom lit-element

我正在更改 Lit Web 组件的属性,但更改后的值不会呈现。

我有一个观察到的数组:reports[],它将使用从其余 api 获取的报告 url 填充到firstUpdated() 中。数组的加载是通过以下方式完成的:

this.reports.push({ "name" : report.Name, "url" : this.apiUrl + "/" + report.Name + "?rs:embed=true" });

见下文:

import { LitElement, html, css } from 'lit';
import {apiUrl, restApiUrl} from '../../config';

export default class Homepage extends LitElement {
  static properties = {
    apiUrl: '',
    restApiUrl: '',
    reports: []
  }

...

  constructor() {
    super();

    this.apiUrl = apiUrl;
    this.restApiUrl= restApiUrl;
    this.reports = []; 
  }

  firstUpdated() {
    ...
    // Fetch all reports from restApiUrl:
    rsAPIDetails(restApiUrl).then(reports =>{     
      for(const report of reports.value)
      {       
        rsAPIDetails(restApiUrl + "(" + report.Id + ")/Policies").then(policies => {
          for(const policy of policies.Policies)
          {
            if(policy.GroupUserName.endsWith(usernamePBI))
            {
              for(const role of policy.Roles)
              {
                if(role != null && (role.Name== "Browser" || role.Name== "Content Manager")) 
                {
                  // User has access to this report so i'll push it to the list of reports that will show in the navbar:
                  this.reports.push({ "name" : report.Name, "url" : this.apiUrl + "/" + report.Name + "?rs:embed=true" });
                }
              }
            }
          }
        });
      }
    }).then(q => {
      console.log(this.reports);
    });
  }

  render() {
    return html`
      <div id="sidenav" class="sidenav">
        ...
        <div class="menucateg">Dashboards</div>
        ${this.reports.map((report) =>
          html`<a @click=${() => this.handleMenuItemClick(report.url)}>${report.name}</a>`
        )}
        <div class="menucateg">Options</div>
      </div>
    `;
  }

在控制台我可以清楚地看到数组加载了正确的值。 但是 render() 函数不会使用 reports[] 的新值更新 Web 组件: The links should be added inside 'Dashboards' div

如果我用值(在 ctor 中)静态填充 reports[],它就会很好地呈现链接。

那么为什么当观察到的数组发生变化时组件没有更新呢?

谢谢!

最佳答案

Array.push 会改变数组,但不会更改内存中的实际值。

要让 LitElement 跟踪数组和对象的更新,值的更新必须是不可变的。

例如,我们可以通过以下方式使您的示例正常工作:

const newReports = this.reports.slice();
newReports.push({ "name" : report.Name, "url" : this.apiUrl + "/" + report.Name + "?rs:embed=true" });
this.reports = newReports;

或者使用数组扩展

this.reports = [...this.reports, { "name" : report.Name, "url" : this.apiUrl + "/" + report.Name + "?rs:embed=true" }]

这样做的原因是,当您执行 this.reports.push() 时,您实际上并没有更改 this.reports 的“引用”,您只是向其中添加一个对象。另一方面,当您使用 this.reports = ... 重新定义属性时,您正在更改“引用”,因此 LitElement 知道该值已更改,并且它将触发重新定义-渲染。

对于对象来说也是如此。假设您有一个属性 obj。如果您仅通过添加属性来更新对象,则该元素不会重新呈现。

this.obj.newProp = 'value';

但是如果通过复制对象并添加属性来整体重新定义对象属性,则会导致元素正确更新。

this.obj = {...this.obj, newProp: 'value'}

您可以使用 updated 查看正在跟踪和更新的值方法。

关于web - 属性更改时点亮的 Web 组件未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70303015/

相关文章:

javascript - 在 shadow dom 中选择元素

javascript - 如何让一个部分填满整个屏幕?

python - Django:即使不在 settings.py 中,APPEND_SLASH 是否设置为 True?

java - 为什么我的变量不会被 Autowiring ?

components - 在 vue.js 中将数据从父组件传递到子组件

components - AEM 6.2(在此处拖动组件)Parsys 高度 0px

java - 部署在 Tomcat 7.0.52 中的每个应用程序的 web.xml 都消失了

javascript - 如何在同级 vue.js 组件之间共享数据?

javascript - 如何克隆/复制 DOM 节点的影子 Dom?

javascript - 如何一起使用 Polymer polyfill