使用 Attribute 设置按钮样式

Permalink to "使用 Attribute 设置按钮样式"

现在只剩下按钮功能了。这个组件应该允许用户提供一个单一的点赞或踩评分,并给用户提供视觉反馈。在这一步中,你将做一些准备工作:

然后在接下来的步骤中,你将添加事件监听器来处理按钮点击并设置 vote attribute。

首先添加以下代码:

index.html

Permalink to "index.html"
<template>
<style>
...

:host([vote=up]) .thumb_up {
fill: green;
}
:host([vote=down]) .thumb_down {
fill: red;
}
</style>
</template>

在 Shadow DOM 中,:host 选择器指向 shadow root 所附加的节点或自定义元素。

在这种情况下,如果 vote attribute 为 "up"(例如 <rating-element vote="up">"),它会将点赞按钮变为绿色。

如果 vote 为 "down"(例如 <rating-element vote="down">"),则会将踩按钮变为红色。

现在,通过创建 vote 的反射属性 / attribute 来实现此逻辑,类似于你实现 rating 的方式。从属性的 setter 和 getter 开始:

export class RatingElement extends HTMLElement {
private _rating = 0;
private _vote: 'up'|'down'|null = null;

...

set vote(newValue) {
const oldValue = this._vote;
if (newValue === oldValue) {
return;
}

if (newValue === 'up') {
if (oldValue === 'down') {
this.rating += 2;
} else {
this.rating += 1;
}
} else if (newValue === 'down') {
if (oldValue === 'up') {
this.rating -= 2;
} else {
this.rating -= 1;
}
}

this._vote = newValue;
this.setAttribute('vote', newValue!);
}

get vote() {
return this._vote;
}
}
export class RatingElement extends HTMLElement {
_vote = null;

...

set vote(newValue) {
const oldValue = this._vote;
if (newValue === oldValue) {
return;
}

if (newValue === 'up') {
if (oldValue === 'down') {
this.rating += 2;
} else {
this.rating += 1;
}
} else if (newValue === 'down') {
if (oldValue === 'up') {
this.rating -= 2;
} else {
this.rating -= 1;
}
}

this._vote = newValue;
this.setAttribute('vote', newValue);
}

get vote() {
return this._vote;
}
}

将 _vote 实例属性初始化为类成员属性 null,在 setter 中检查新值是否不同。如果不同,则相应地调整 rating,重要的是,使用 this.setAttribute 将 vote attribute 反射回宿主元素。

不建议在 vote setter 中以这种方式操作 rating。

这不是更新 rating 最高效的方式,但对本教程来说是最方便的方式。

处理 "vote" Attribute 变化

Permalink to "处理 "vote" Attribute 变化"

接下来,为 vote 设置 attribute 绑定:

static get observedAttributes() {
return ['rating', 'vote'];
}

attributeChangedCallback(attributeName: string, _oldValue: string, newValue: string) {
if (attributeName === 'rating') {
const newRating = Number(newValue);

this.rating = newRating;
} else if (attributeName === 'vote') {
this.vote = newValue as 'up'|'down';
}
}
static get observedAttributes() {
return ['rating', 'vote'];
}

attributeChangedCallback(attributeName, _oldValue, newValue) {
if (attributeName === 'rating') {
const newRating = Number(newValue);

this.rating = newRating;
} else if (attributeName === 'vote') {
this.vote = newValue;
}
}

这与你之前处理 rating attribute 绑定的过程相同:

在浏览器开发者工具控制台中通过 $0.setAttribute('vote', 'up') 将 vote attribute 设置为 "up" 来验证是否正常工作。