现在可以开始定位元素了。

更新 render 方法的顶部,如下所示:

render() {
const p = this.selectedInternal;
const s = (this.selectedInternal =
this.hasValidSelected() ? this.selected : this.selectedInternal);
const shouldMove = this.hasUpdated && s !== p;
const atStart = p === 0;
const toStart = s === 0;
const atEnd = p === this.maxSelected;
const toEnd = s === this.maxSelected;
const shouldAdvance = shouldMove &&
(atEnd ? toStart : atStart ? !toEnd : s > p);
const delta = (shouldMove ? Number(shouldAdvance) || -1 : 0) * 100;
this.left -= delta;
const animateLeft = `${this.left}%`;
const selectedLeft = `${-this.left}%`;
const previousLeft = `${-this.left - delta}%`;

这里有一些代码需要理解。它利用了之前添加的代码来帮助定位元素。

首先,shouldMove 基于 selectedInternal 跟踪属性的变化来计算, 并使用 ReactiveElement 的 hasUpdated 属性来避免在首次渲染时运行动画。

然后,计算 shouldAdvance,使得当选中的项目增加时位置前进, 并在循环到开头或结尾时反转定位方向。

移动 delta 根据 shouldMoveshouldAdvance 来计算。 left 属性存储一个 % 值,表示插槽"容器"元素应该定位的位置, 并使用移动 delta 来计算。left 作为元素上的属性存储, 这样即使 selected 属性没有变化,重新渲染也会应用适当的值。

最后,位置根据 left 属性来设置。动画容器(animateLeft)使用存储在 left 中的位置。选中的项目(selectedLeft)需要显示出来, 所以它是 left 的反值。而对于前一个项目(previousLeft), 它根据移动 delta 放置在选中项目的左侧或右侧。

如果以上步骤都正确完成,当你点击和 Shift+点击元素时, 轮播的行为应与上一步相同。

如果你想验证前一个项目的位置,打开 styles 模块, 移除 :host 选择器中的 overflow: hidden