现在只剩下按钮功能了。这个组件应该允许用户提供一个单一的点赞或踩评分,并给用户提供视觉反馈。在这一步中,你将做一些准备工作:
vote 属性和 attribute,类似于你之前添加的 rating 属性。vote attribute 的当前值,为点赞和踩按钮添加新的样式。然后在接下来的步骤中,你将添加事件监听器来处理按钮点击并设置 vote attribute。
首先添加以下代码:
<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 绑定:
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 绑定的过程相同:
'vote' 添加到 observedAttributes。attributeChangedCallback 中设置 vote 属性。在浏览器开发者工具控制台中通过 $0.setAttribute('vote', 'up') 将 vote attribute 设置为 "up" 来验证是否正常工作。