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

Posted

技术标签:

【中文标题】点亮的 Web 组件未在属性更改时更新【英文标题】:Lit web component not updated on attribute change 【发布时间】:2022-01-15 01:23:04 【问题描述】:

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

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

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 中)静态填充报告[],它会很好地呈现链接。

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

谢谢!

【问题讨论】:

【参考方案1】:

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 组件未在属性更改时更新的主要内容,如果未能解决你的问题,请参考以下文章

组件未在商店更改时更新 - Vuex

Vue props 数据未在子组件中更新

Ember - 组件属性未在模板 hbs 中更新

如何调试反应路由器未在 url 更改时加载组件

计算属性未在道具更改时更新

计算数据未在 Vue 中更新