From aaa6d2897da47bf7e72ca3d286ce231617f7ac62 Mon Sep 17 00:00:00 2001 From: fanxiaohao Date: Wed, 1 Mar 2023 14:10:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.js | 9 ++++++++- src/config.js | 2 ++ src/reactive.js | 20 ++++++++++++++++++-- src/render.js | 4 +++- src/utils.js | 6 +++--- 5 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/app.js b/src/app.js index e766483..9c3bb17 100644 --- a/src/app.js +++ b/src/app.js @@ -5,19 +5,25 @@ import { ITEM_HEIGHT } from './config' import { setAnimationFrame } from './utils' (function () { + // 获取DOM元素 const oScroller = document.querySelector('#J_ScrollWrapper') const oList = oScroller.querySelector('.list-wrapper') + // 对数据做响应式处理 const $state = reactive(oList) const init = () => { + // 初始化数据 initData(1, 20) + // 渲染 render($state.currentData, $state.paddingSet, oList) + // 事件处理 bindEvent() } const initData = (init, count) => { + // 设置数据 setDataSource(init, count) + // 设置当前页面的数据 setCurrentData() - console.log($state.dataSource, $state.currentData) } function bindEvent() { @@ -25,6 +31,7 @@ import { setAnimationFrame } from './utils' } function handleScroll() { + // 使用 requestAnimationFrame 优化 setAnimationFrame(() => { $state.startIndex = Math.floor(this.scrollTop / ITEM_HEIGHT) }) diff --git a/src/config.js b/src/config.js index fff9976..2b53eba 100644 --- a/src/config.js +++ b/src/config.js @@ -1,4 +1,6 @@ +// 每一项高度,定义高度的时候记得计算边框和mr/pd export const ITEM_HEIGHT = 101 // 获取高度后/每一项的到高度,然后取最大,也就是如果有小数再+1,但是有可能会出现一屏还有一半的item情况,所以还要再+1 export const MAX_ITEM_COUNT = Math.ceil(document.querySelector('#J_ScrollWrapper').offsetHeight / ITEM_HEIGHT) + 1 +// FPS export const TIME_PER_FPS = (1000 / 30) diff --git a/src/reactive.js b/src/reactive.js index f868237..a54d96c 100644 --- a/src/reactive.js +++ b/src/reactive.js @@ -4,6 +4,7 @@ import { update, updatePaddingSet } from './render' const $state = {} +// 定义一个 data对象 方便之后进行代理 const data = { dataSource: [], currentData: [], @@ -17,49 +18,60 @@ const data = { export function reactive(list) { Object.defineProperties($state, { + // 数据 dataSource: { get() { return data.dataSource }, set(v) { data.dataSource = v - // set currentData } }, + // 当前页面数据 currentData: { get() { return data.currentData }, set(v) { data.currentData = v - update($state.currentData, list) + // 修改 currentData 数据的同时,也会更新 当前 item + update(data.currentData, list) } }, + // 开始下标 startIndex: { get() { return data.startIndex }, set(v) { + // start下标和当前下标不相等,就更新start下标 if ($state.startIndex !== v) { data.startIndex = v + // 开始下标改变了,当前内容也要改变 setCurrentData() + // 最后下标 >= 整体长度 则返回 $state.endIndex >= $state.dataSource.length - 1 + // todo 不清晰 && setDataSource($state.dataSource.length + 1, $state.dataSource.length * 2) + // 设置pd setPaddingSet() } } }, + // 结束下标 endIndex: { get() { return setEndIndex() } }, + // padding 值 paddingSet: { get() { return data.paddingSet }, set(v) { data.paddingSet = v + // 设置 pd 时候要更新 DOM 的 pd updatePaddingSet($state.paddingSet, list) } } @@ -75,6 +87,8 @@ function setEndIndex() { } export function setDataSource(init, count) { + console.log(...$state.dataSource) + // 给dataSource重新赋值 $state.dataSource = [ ...$state.dataSource, ...getData(init, count) @@ -83,6 +97,7 @@ export function setDataSource(init, count) { export function setCurrentData() { let StartIndex = resetStartIndex() + // 截取一屏的内容 $state.currentData = $state.dataSource.slice(StartIndex, $state.endIndex) } @@ -95,5 +110,6 @@ export function setPaddingSet() { } export function resetStartIndex() { + // 初始位置 小于等于 一屏的高度则起始位置依然是 0 因为我们是 2 屏 ,如果起始位置大于一屏高度 则返回差值 return $state.startIndex <= MAX_ITEM_COUNT ? 0 : $state.startIndex - MAX_ITEM_COUNT } diff --git a/src/render.js b/src/render.js index f78f630..76cd57b 100644 --- a/src/render.js +++ b/src/render.js @@ -12,9 +12,11 @@ export function render(currentData, paddingSet, list) { } export function update(currentData, list) { + // 选出所有 item const oItems = list.querySelectorAll('.list-item') - + // 替换 所有 item oItems.forEach((item, index) => { + // 插入新值 item.innerText = currentData[index] }) } diff --git a/src/utils.js b/src/utils.js index 84b23ed..1eab4ed 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,20 +1,20 @@ import { TIME_PER_FPS } from './config' - +// 构造数组数据 export function getData(init, count) { const arr = [] for (let i = init; i <= count; i ++) { arr.push(i) } - return arr } export function setAnimationFrame(cb) { let beginTime = Date.now() - + // 浏览器下一次重绘之前安排一个回调函数,以便在下一帧中进行更新 requestAnimationFrame(function rf() { const endTime = Date.now() + cb() if (endTime - beginTime >= TIME_PER_FPS) { beginTime = endTime