gpt4 book ai didi

javascript - Vue.js - 提高无限列表循环的性能

转载 作者:太空宇宙 更新时间:2023-11-04 06:03:59 24 4
gpt4 key购买 nike

我需要一个用户列表来垂直无限循环。我知道对于这类内容我应该使用“translateY”而不是“top”——但我不知道该怎么做。我已经完成了“顶级”版本并且可以正常工作。有什么改进的想法吗?

谢谢大家!

Example in Codepen

<div id="app">
<div id="rows">
<div class="row" v-for="row in rows" v-bind:style="{ top: row.top + 'px' }">
{{row.id}}
</div>
</div>
</div>

<script>
const app = new Vue({
el: '#app',
data() {
return {
rows: []
}
},
created() {
for (let i = 0; i < 30; i++) {
this.rows.push({
id: i,
top: i * 40
})
}
setInterval(() => {
window.requestAnimationFrame(this.update);
}, 16);
},
methods: {
update() {
this.rows.forEach(row => {
row.top -= 0.5
});
if (this.rows[0].top <= -40) {
this.rows.push({
id: this.rows[0].id,
top: (this.rows.length - 1) * 40
})
this.rows.shift();
}
}
}
})
</script>
<style>
#rows {
position: relative;
}
.row {
position: absolute;
width: 100%;
height: 40px;
border: 1px solid black;
}
</style>

最佳答案

这是我的尝试:

new Vue({
el: '#app',

data() {
const rows = []

for (let i = 0; i < 30; i++) {
rows.push({
id: i
})
}

return {
offset: 0,
rows
}
},

mounted () {
this.frameTime = Date.now()

const animate = () => {
this.animationId = requestAnimationFrame(() => {
this.update()
animate()
})
}

animate()
},

beforeDestroy () {
cancelAnimationFrame(this.animationId)
},

methods: {
update() {
const now = Date.now()
const elapsed = now - this.frameTime

this.offset -= elapsed / 16
this.frameTime = now

if (this.offset < -400) {
while (this.offset < -40) {
this.rows.push(this.rows.shift())
this.offset += 40
}
}
}
}
})
* {
box-sizing: border-box;
}

#rows {
border: 1px solid #f00;
height: 200px;
overflow: hidden;
}

.row {
width: 100%;
height: 40px;
border: 2px solid black;
}
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id="app">
<div id="rows">
<div :style="{ transform: `translateY(${Math.round(offset)}px)` }">
<div
v-for="row in rows"
:key="row.id"
class="row"
>
{{row.id}}
</div>
</div>
</div>
</div>

您不必进行我所做的所有更改,如果您愿意,可以有选择地进行大部分更改。主要变化是:

  1. key在列表项上,以便 Vue 移动 DOM 节点,而不是在随机播放发生时更新所有节点。
  2. 使用包装器 <div>这样实际上只有一个元素在移动(我去掉了绝对定位作为其中的一部分)。
  3. 使用 translateY , 根据要求。
  4. 摆脱 setInterval , 你应该只需要 requestAnimationFrame为了这。通过跟踪流逝的时间来控制动画速度。
  5. 当一行跳转时,我只是将对象移动到数组的末尾,而不是制作副本。
  6. 当组件被销毁时,动画被取消。

更新:

三个进一步的变化:

  1. 我添加了 box-sizing: border-box修复计算中的 2px 误差。
  2. DOM 节点重新排序现在被批处理为每 400 像素仅发生一次。不知道这是否真的是个好主意,对于这样一个简单的示例,它并没有真正产生任何影响。
  3. 我四舍五入了 translateY使用整个像素。对我来说,这看起来稍微好一点,但在像素比更高的屏幕上,我可以想象它可能看起来更糟。

根据具体情况,可能会进行进一步的优化。

  1. 可以省略不可见的行。
  2. 通过应用 translateY 可以完全避免重新排序到每一行,尽管对于可能不切实际的大量行。

使用过渡或 CSS 动画对此进行动画处理会很棘手,因为需要行跳回到底部。如果每一行都是独立的动画,我不确定保持所有动画同步会有多容易。

关于javascript - Vue.js - 提高无限列表循环的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57039963/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com