Lit Web 组件未在属性更改时更新
Lit web component not updated on attribute change
我正在更改 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
如果我用值静态填充报告[](在构造函数中),它会很好地呈现链接。
那么为什么在观察到的数组发生变化时组件没有更新?
谢谢!
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 方法查看正在跟踪和更新的值。
我正在更改 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
如果我用值静态填充报告[](在构造函数中),它会很好地呈现链接。
那么为什么在观察到的数组发生变化时组件没有更新?
谢谢!
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 方法查看正在跟踪和更新的值。