♻️(component): 使用 setup script 重构 scroll 组件
This commit is contained in:
		
							parent
							
								
									844f3fd0cf
								
							
						
					
					
						commit
						3b1849fb70
					
				| @ -1,44 +1,34 @@ | |||||||
| .scrollbar-box { | .layui-scroll { | ||||||
|   height: 100%; |   height: 100%; | ||||||
|   overflow: hidden !important; |   overflow: hidden !important; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .scrollbar-y { | .layui-scroll-y { | ||||||
|   position: relative; |   position: relative; | ||||||
|   height: 100%; |   height: 100%; | ||||||
|   .scroll-wrap { | 
 | ||||||
|  |   .layui-scroll-wrap { | ||||||
|     height: 100%; |     height: 100%; | ||||||
|     overflow-y: scroll; |     overflow-y: scroll; | ||||||
|     scrollbar-width: none; /* firefox */ |     scrollbar-width: none; | ||||||
|     -ms-overflow-style: none; |     -ms-overflow-style: none; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   .scrollbar-track { |   .layui-scroll-track { | ||||||
|     position: absolute; |     position: absolute; | ||||||
|     top: 0; |     top: 0; | ||||||
|     right: 0; |     right: 0; | ||||||
|     bottom: 0; |     bottom: 0; | ||||||
|     border-radius: 8px; |     border-radius: 8px; | ||||||
|     z-index: 20; |     z-index: 20; | ||||||
|     .scrollbar-thumb { |     .layui-scroll-thumb { | ||||||
|       margin: 0 auto; |       margin: 0 auto; | ||||||
|       border-radius: 6px; |       border-radius: 6px; | ||||||
|       cursor: default; |       cursor: default; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| .scrollbar-y ::-webkit-scrollbar { | 
 | ||||||
|  | .layui-scroll-y ::-webkit-scrollbar { | ||||||
|   display: none; |   display: none; | ||||||
| } | } | ||||||
| //移动端隐藏自定义滚动条 |  | ||||||
| .hide.scrollbar-box .scrollbar-track { |  | ||||||
|   display: none; |  | ||||||
| } |  | ||||||
| //移动端显示原生滑块 |  | ||||||
| .hide.scrollbar-box .scrollbar-y ::-webkit-scrollbar { |  | ||||||
|   display: block; |  | ||||||
| } |  | ||||||
| .hide.scrollbar-box .scrollbar-y .scroll-wrap { |  | ||||||
|   scrollbar-width: auto; |  | ||||||
|   -ms-overflow-style: scrollbar; |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -1,16 +1,16 @@ | |||||||
| <template> | <template> | ||||||
|   <div |   <div | ||||||
|     class="scrollbar-box" |     class="layui-scroll" | ||||||
|     :class="{ hide: winWidth < 500 }" |     :class="{ hide: data.winWidth < 500 }" | ||||||
|     :style="{ height: height }" |     :style="{ height: height }" | ||||||
|   > |   > | ||||||
|     <div class="scrollbar-y"> |     <div class="layui-scroll-y"> | ||||||
|       <div ref="scrollRef" class="scroll-wrap" @scroll="onMosewheel"> |       <div ref="scrollRef" class="layui-scroll-wrap" @scroll="onMosewheel"> | ||||||
|         <slot></slot> |         <slot></slot> | ||||||
|       </div> |       </div> | ||||||
|       <div |       <div | ||||||
|         ref="barRef" |         ref="barRef" | ||||||
|         class="scrollbar-track" |         class="layui-scroll-track" | ||||||
|         :style="{ |         :style="{ | ||||||
|           backgroundColor: heightPre == 1 ? 'rgba(0,0,0,0)' : slotColor, |           backgroundColor: heightPre == 1 ? 'rgba(0,0,0,0)' : slotColor, | ||||||
|         }" |         }" | ||||||
| @ -21,12 +21,12 @@ | |||||||
|        --> |        --> | ||||||
|         <div |         <div | ||||||
|           :style="{ |           :style="{ | ||||||
|             height: barHeight + 'px', |             height: data.barHeight + 'px', | ||||||
|             width: scrollWidth + 'px', |             width: scrollWidth + 'px', | ||||||
|             transform: 'translateY(' + translateY + 'px)', |             transform: 'translateY(' + data.translateY + 'px)', | ||||||
|             backgroundColor: heightPre == 1 ? 'rgba(0,0,0,0)' : scrollColor, |             backgroundColor: data.heightPre == 1 ? 'rgba(0,0,0,0)' : scrollColor, | ||||||
|           }" |           }" | ||||||
|           class="scrollbar-thumb" |           class="layui-scroll-thumb" | ||||||
|           @mousedown.stop.prevent="moveStart" |           @mousedown.stop.prevent="moveStart" | ||||||
|         ></div> |         ></div> | ||||||
|       </div> |       </div> | ||||||
| @ -34,7 +34,13 @@ | |||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script> | <script lang="ts"> | ||||||
|  | export default { | ||||||
|  |   name: "LayScroll" | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <script lang="ts" setup> | ||||||
| import "./index.less"; | import "./index.less"; | ||||||
| import { | import { | ||||||
|   defineComponent, |   defineComponent, | ||||||
| @ -43,62 +49,57 @@ import { | |||||||
|   nextTick, |   nextTick, | ||||||
|   reactive, |   reactive, | ||||||
|   onUnmounted, |   onUnmounted, | ||||||
|  |   ref, | ||||||
| } from "vue"; | } from "vue"; | ||||||
| export default defineComponent({ | 
 | ||||||
|   name: "LayScroll", | export interface LayScrollProps { | ||||||
|   props: { |   height: string; | ||||||
|     height: { |   slotColor: string; | ||||||
|       type: String, |   scrollColor: string; | ||||||
|       default: "100%", |   scrollWidth: number; | ||||||
|     }, | } | ||||||
|     slotColor: { | 
 | ||||||
|       //滑块槽颜色 :slotColor="'red'" | const props = withDefaults(defineProps<LayScrollProps>(), { | ||||||
|       type: String, |   height: "100%", | ||||||
|       default: "rgba(0,0,0,0)", |   slotColor: "rgba(0,0,0,0)", | ||||||
|     }, |   scrollColor: "#eeeeee", | ||||||
|     scrollColor: { |   scrollWidth: 6, | ||||||
|       //滑块颜色  :scrollColor="'red'" | }); | ||||||
|       type: String, | 
 | ||||||
|       default: "#eeeeee", | const emit = defineEmits(["arrive"]); | ||||||
|     }, | 
 | ||||||
|     scrollWidth: { | const scrollRef = ref<HTMLElement | null>(null); | ||||||
|       //滑块宽度 :scrollWidth="7" | const barRef = ref<HTMLElement | null>(null); | ||||||
|       type: Number, | 
 | ||||||
|       default: 6, | const data = reactive({ | ||||||
|     }, |  | ||||||
|   }, |  | ||||||
|   setup(props, ctx) { |  | ||||||
|     const data = reactive({ |  | ||||||
|       scrollRef: null, // 内容盒子 |  | ||||||
|       barRef: null, // 滚动条轨道 |  | ||||||
|   translateY: 0, // 滚动块平移的距离 |   translateY: 0, // 滚动块平移的距离 | ||||||
|   heightPre: 0, // 可视高度和内容高度比 |   heightPre: 0, // 可视高度和内容高度比 | ||||||
|   barHeight: 0, // 滑块高度 |   barHeight: 0, // 滑块高度 | ||||||
|   winWidth: document.body.clientWidth, //初始化浏览器页面宽度 |   winWidth: document.body.clientWidth, //初始化浏览器页面宽度 | ||||||
|     }); | }); | ||||||
|     let time = null; // 定时器 | let time = null; // 定时器 | ||||||
|     let isMove = false; // 判断鼠标是否点击滑块(为松开) | let isMove = false; // 判断鼠标是否点击滑块(为松开) | ||||||
|     let moveClientY = 0; // 鼠标点击滑块时,相对滑块的位置 | let moveClientY = 0; // 鼠标点击滑块时,相对滑块的位置 | ||||||
|     let trackHeight = 0; // 滚动条轨道高度 | let trackHeight = 0; // 滚动条轨道高度 | ||||||
|     let wrapHeight = 0; // 容器高度(可视高度) | let wrapHeight = 0; // 容器高度(可视高度) | ||||||
|     let wrapContentHeight = 0; // 内容高度(可滚动内容的高度) | let wrapContentHeight = 0; // 内容高度(可滚动内容的高度) | ||||||
| 
 | 
 | ||||||
|     // 页面挂载后计算滚动条 | // 页面挂载后计算滚动条 | ||||||
|     onMounted(() => { | onMounted(() => { | ||||||
|   monitorWindow(); //监听窗口尺寸 |   monitorWindow(); //监听窗口尺寸 | ||||||
|   monitorScrollBar(); //监听内容元素尺寸 |   monitorScrollBar(); //监听内容元素尺寸 | ||||||
|   nextTick(() => { |   nextTick(() => { | ||||||
|     //dom渲染后 |     //dom渲染后 | ||||||
|     calculationLength(); //初始化延迟更新滚动条 |     calculationLength(); //初始化延迟更新滚动条 | ||||||
|   }); |   }); | ||||||
|     }); | }); | ||||||
|     // 页面卸载清除定时器 | // 页面卸载清除定时器 | ||||||
|     onUnmounted(() => { | onUnmounted(() => { | ||||||
|   window.clearInterval(time); |   window.clearInterval(time); | ||||||
|   time = null; |   time = null; | ||||||
|     }); | }); | ||||||
|     // 监听页面尺寸改变计算滚动条 | // 监听页面尺寸改变计算滚动条 | ||||||
|     const monitorWindow = function () { | const monitorWindow = function () { | ||||||
|   let time; //定时器,防抖,窗口持续变化,延迟更新滚动条 |   let time; //定时器,防抖,窗口持续变化,延迟更新滚动条 | ||||||
|   window.addEventListener("resize", () => { |   window.addEventListener("resize", () => { | ||||||
|     data.winWidth = document.body.clientWidth; //页面改变监听宽度控制移动端隐藏滚动条 |     data.winWidth = document.body.clientWidth; //页面改变监听宽度控制移动端隐藏滚动条 | ||||||
| @ -109,15 +110,17 @@ export default defineComponent({ | |||||||
|       initScrollListner(); |       initScrollListner(); | ||||||
|     }, 500); |     }, 500); | ||||||
|   }); |   }); | ||||||
|     }; | }; | ||||||
| 
 | 
 | ||||||
|     //监听内容元素尺寸变化 | //监听内容元素尺寸变化 | ||||||
|     const monitorScrollBar = function () { | const monitorScrollBar = function () { | ||||||
|       var monitorUl = data.scrollRef.children[0]; |   var monitorUl = scrollRef.value.children[0]; | ||||||
|   // var monitorDiv= document;    // 监听document |   // var monitorDiv= document;    // 监听document | ||||||
|   let MutationObserver = |   let MutationObserver = | ||||||
|     window.MutationObserver || |     window.MutationObserver || | ||||||
|  |     // @ts-ignore | ||||||
|     window.WebKitMutationObserver || |     window.WebKitMutationObserver || | ||||||
|  |     // @ts-ignore | ||||||
|     window.MozMutationObserver; |     window.MozMutationObserver; | ||||||
|   let observer = new MutationObserver(function (mutations) { |   let observer = new MutationObserver(function (mutations) { | ||||||
|     // console.log("内容元素变化更新滚动条"); |     // console.log("内容元素变化更新滚动条"); | ||||||
| @ -130,10 +133,10 @@ export default defineComponent({ | |||||||
|     attributes: true, |     attributes: true, | ||||||
|     childList: true, |     childList: true, | ||||||
|   }); |   }); | ||||||
|     }; | }; | ||||||
| 
 | 
 | ||||||
|     // 初始化延迟监听滚动条 | // 初始化延迟监听滚动条 | ||||||
|     const calculationLength = function () { | const calculationLength = function () { | ||||||
|   // 直接执行initScrollListner函数,获取滚动条长度部准确 |   // 直接执行initScrollListner函数,获取滚动条长度部准确 | ||||||
|   // 因为页面渲染有延迟,获取dom元素需要延迟 |   // 因为页面渲染有延迟,获取dom元素需要延迟 | ||||||
|   // 每间隔10毫秒更新滑块长度 |   // 每间隔10毫秒更新滑块长度 | ||||||
| @ -146,11 +149,11 @@ export default defineComponent({ | |||||||
|     window.clearInterval(time); |     window.clearInterval(time); | ||||||
|     time = null; |     time = null; | ||||||
|   }, 2000); |   }, 2000); | ||||||
|     }; | }; | ||||||
|     // 计算滚动条高度 | // 计算滚动条高度 | ||||||
|     const initScrollListner = function () { | const initScrollListner = function () { | ||||||
|       let scroll = data.scrollRef; |   let scroll = scrollRef.value; | ||||||
|       let bar = data.barRef; |   let bar = barRef.value; | ||||||
|   // scroll有时候拿不到元素,要判断一下 |   // scroll有时候拿不到元素,要判断一下 | ||||||
|   if (scroll) { |   if (scroll) { | ||||||
|     wrapContentHeight = scroll.scrollHeight; |     wrapContentHeight = scroll.scrollHeight; | ||||||
| @ -162,9 +165,9 @@ export default defineComponent({ | |||||||
|     // 滑动块的高度 根据 容器和内容的比  乘以 滚动轨道 计算出 滑动块的高度 |     // 滑动块的高度 根据 容器和内容的比  乘以 滚动轨道 计算出 滑动块的高度 | ||||||
|     data.barHeight = data.heightPre * trackHeight; |     data.barHeight = data.heightPre * trackHeight; | ||||||
|   } |   } | ||||||
|     }; | }; | ||||||
|     // 内容滚动时,计算滑块移动的距离 | // 内容滚动时,计算滑块移动的距离 | ||||||
|     const onMosewheel = function (e) { | const onMosewheel = function (e) { | ||||||
|   // scrollTop页面顶部滚出的高度 |   // scrollTop页面顶部滚出的高度 | ||||||
|   // offsetHeight页面可视区域高度 |   // offsetHeight页面可视区域高度 | ||||||
|   // scrollHeight页面正文全文高度 |   // scrollHeight页面正文全文高度 | ||||||
| @ -180,13 +183,13 @@ export default defineComponent({ | |||||||
|     // 滚出高度 + 可视区域高度 == 内容高度 |     // 滚出高度 + 可视区域高度 == 内容高度 | ||||||
|     arrive("bottom"); |     arrive("bottom"); | ||||||
|   } |   } | ||||||
|     }; | }; | ||||||
|     // 到达顶部或者底部通知父级元素 | // 到达顶部或者底部通知父级元素 | ||||||
|     const arrive = function name(tb) { | const arrive = function name(tb) { | ||||||
|       ctx.emit("arrive", tb); |   emit("arrive", tb); | ||||||
|     }; | }; | ||||||
|     // 鼠标点击滑块时 | // 鼠标点击滑块时 | ||||||
|     const moveStart = function (e) { | const moveStart = function (e) { | ||||||
|   isMove = true; |   isMove = true; | ||||||
|   // clientY:当鼠标事件发生时,鼠标相对于浏览器(这里说的是浏览器的有效区域)y轴的位置 |   // clientY:当鼠标事件发生时,鼠标相对于浏览器(这里说的是浏览器的有效区域)y轴的位置 | ||||||
|   // data.translateY 滚动块平移的距离 |   // data.translateY 滚动块平移的距离 | ||||||
| @ -194,9 +197,9 @@ export default defineComponent({ | |||||||
|   moveClientY = e.clientY - data.translateY; |   moveClientY = e.clientY - data.translateY; | ||||||
|   moveTo(); //移动时 |   moveTo(); //移动时 | ||||||
|   moveEnd(); //鼠标松开时 |   moveEnd(); //鼠标松开时 | ||||||
|     }; | }; | ||||||
|     // 鼠标移动,改变thumb的位置以及容器scrollTop的位置 | // 鼠标移动,改变thumb的位置以及容器scrollTop的位置 | ||||||
|     const moveTo = function () { | const moveTo = function () { | ||||||
|   document.onmousemove = (e) => { |   document.onmousemove = (e) => { | ||||||
|     // 移动时候判断是不是松开,松开就不在执行滑块移动操作 |     // 移动时候判断是不是松开,松开就不在执行滑块移动操作 | ||||||
|     if (isMove) { |     if (isMove) { | ||||||
| @ -212,24 +215,18 @@ export default defineComponent({ | |||||||
|         data.translateY = e.clientY - moveClientY; |         data.translateY = e.clientY - moveClientY; | ||||||
|       } |       } | ||||||
|       // 计算出内容盒子滚出顶部的距离 |       // 计算出内容盒子滚出顶部的距离 | ||||||
|           data.scrollRef.scrollTop = data.translateY / data.heightPre; |       scrollRef.value.scrollTop = data.translateY / data.heightPre; | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|     }; | }; | ||||||
|     // 鼠标从滑块松开时,不在监听滑块移动操作 | // 鼠标从滑块松开时,不在监听滑块移动操作 | ||||||
|     const moveEnd = function () { | const moveEnd = function () { | ||||||
|   document.onmouseup = (e) => { |   document.onmouseup = (e) => { | ||||||
|     if (isMove) { |     if (isMove) { | ||||||
|       isMove = false; |       isMove = false; | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|     }; | }; | ||||||
| 
 | 
 | ||||||
|     return { | let dataRef = toRefs(data); | ||||||
|       ...toRefs(data), |  | ||||||
|       onMosewheel, |  | ||||||
|       moveStart, |  | ||||||
|     }; |  | ||||||
|   }, |  | ||||||
| }); |  | ||||||
| </script> | </script> | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user