现在可以开始定位元素了。
更新 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 根据 shouldMove 和 shouldAdvance 来计算。 left 属性存储一个 % 值,表示插槽"容器"元素应该定位的位置, 并使用移动 delta 来计算。left 作为元素上的属性存储, 这样即使 selected 属性没有变化,重新渲染也会应用适当的值。
最后,位置根据 left 属性来设置。动画容器(animateLeft)使用存储在 left 中的位置。选中的项目(selectedLeft)需要显示出来, 所以它是 left 的反值。而对于前一个项目(previousLeft), 它根据移动 delta 放置在选中项目的左侧或右侧。
如果以上步骤都正确完成,当你点击和 Shift+点击元素时, 轮播的行为应与上一步相同。
如果你想验证前一个项目的位置,打开 styles 模块, 移除 :host 选择器中的 overflow: hidden。