使用 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.setAttributevote 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" 来验证是否正常工作。