商品分類左右聯動

1、先看效果

2、以hooks方法處理,方便復制使用,見代碼

Good.vue文件

<script setup lang="ts" name="goods">import {onMounted, ref, nextTick} from "vue";import useProductScroll from "@/utils/hooks/useProductScroll.ts";import loading from '@/assets/images/loading.gif'import categoryHolder from './images/category-holder.png'import productHolder from './images/product-holder.png'const productList = ref<any[]>([])const refSide = ref()const refMain = ref()const {mark, setMark, setRefSide, setRefMain} = useProductScroll()onMounted(() => {// 模擬productList的數據const tmpList = Array(15).fill(1).map((v, i) => {return {name: `人氣熱賣${i}`,pList: Array(5).fill(1).map((v2, i2) => {return {name: `名字${i}-${i2}`}})}})setTimeout(async () => {productList.value = tmpListawait nextTick()setRefSide(refSide.value)setRefMain(refMain.value)setMark(tmpList[0].name)}, 200)})</script><template><div class="product-limit"><ul class="category-box" ref="refSide"><li v-for="v in productList" :key="v" :class="{'active': v.name===mark}" @click="() => setMark(v.name)" :mark="v.name"><div><van-image :loading-icon="loading" :src="categoryHolder" lazy-load /></div><span>{{v.name}}</span></li><li></li></ul><div class='right-content'><div class="search-box"><van-search shape="round" placeholder="請輸入商品關鍵詞" /></div><ul class="com-product-list" ref="refMain"><li v-for="v in productList" :key="v" :mark="v.name"><div class="c-category-name">{{v.name}}</div><div class="c-detail-box" v-for="v2 in v.pList" :key="v2"><div class="img-show"><van-image :loading-icon="loading" :src="productHolder" lazy-load /></div><div class="product-tro"><p class="c-name">{{v2.name}}</p><p class="c-cut-money"><span>立省11.00元起</span></p><div class="c-money"><div class="c-money-detail">¥&nbsp;<i>5.60</i>起&nbsp;<span>¥19.62</span></div><span class="c-btn-size">選規格</span></div></div></div></li><li class="product-holder"></li></ul></div></div>
</template>

useProductScroll.ts文件

import {ref} from "vue";function getDomStyle(dom: HTMLElement, style: any) {return window.getComputedStyle(dom, null)[style];
}const catchMainMarkDom: {[mark: string]: {dom: HTMLElement,top: number}
} = {}
const catchSideMarkDom: {[mark: string]: {dom: HTMLElement,}
} = {}
const catchMainMarkTop: number[] = []
const sideDomView: {[key: string]: number
} = {}
let timer:any = null
let io:any = nullexport default function useProductScroll() {const mark = ref('')const refSide = ref()const refMain = ref()const setRefSide = (d: HTMLElement) => {if (getDomStyle(d, 'position') === 'static') {d.style.position = 'relative'}refSide.value = d// 判斷是否在可視區域io = new IntersectionObserver(entries => {for (let i=0; i<entries.length; i++) {const dom = entries[i].targetconst m = dom.getAttribute('mark')sideDomView[m as string] = entries[i].intersectionRatio}});// 緩存const children: any = d.childrenfor (let i=0; i<children.length; i++) {const dom = children[i]const mName = dom.getAttribute('mark')if (mName) {io.observe(dom);catchSideMarkDom[mName] = {dom: dom,}}}}const setRefMain = (d: HTMLElement) => {if (getDomStyle(d, 'position') === 'static') {d.style.position = 'relative'}refMain.value = d// 緩存const children: any = d.childrenfor (let i=0; i<children.length; i++) {const dom = children[i]const mName = dom.getAttribute('mark')if (mName) {catchMainMarkDom[mName] = {dom: dom,top: dom.offsetTop}catchMainMarkTop.unshift(dom.offsetTop)}}// 綁定refMain.value.addEventListener('scroll', bindMainScroll)}const setMark = (str: string) => {mark.value = strconst dom = catchMainMarkDom[str]['dom']dom.scrollIntoView({behavior: "smooth"});}const bindMainScroll = (e: any) => {clearTimeout(timer)const scrollTop = e.target.scrollToptimer = setTimeout(() => {// 判斷top值和scroll比較,獲取最近的top值,獲取新的mark值let newTop = 0for (let i=0; i<catchMainMarkTop.length; i++) {if (scrollTop >= catchMainMarkTop[i]) {newTop = catchMainMarkTop[i]break;}}let markName = ''// 通過newTop值,獲取新的mark名稱for (let mName in catchMainMarkDom) {if (catchMainMarkDom[mName]['top'] === newTop) {markName = mNamebreak}}if (mark.value === markName) return;mark.value = markNameconst isView = sideDomView[markName] > 0if (!isView) {catchSideMarkDom[markName]['dom'].scrollIntoView({behavior: "smooth"});}}, 200)}const unbind = () => {refMain.value.removeEventListener('scroll', bindMainScroll)io?.disconnect()io = null}return {mark,setMark,setRefSide,setRefMain,unbind}
}

3、使用,hooks拋出了5個方法,作用分別是:
mark:標示字符,用于判斷分類

setMark:當分類點擊時,傳入mark值

setRefSide:傳入dom元素,分類的scroll元素

setRefMain:傳入dom元素,商品的scroll元素

unbind:組件卸載時調用

4、使用規則

a、用原生滾動

b、需要在頁面渲染后使用

c、依次調用setRefSide,setRefMain,setMark

d、在分類列表和產品列表,scroll元素的子元素,需要綁定mark標示,用于匹配

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/43833.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/43833.shtml
英文地址,請注明出處:http://en.pswp.cn/web/43833.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

el-table 鼠標移入更改懸停背景顏色

鼠標懸停時需要更改當前行背景顏色&#xff0c;一開始寫的顏色會改變&#xff0c;但是一閃而過就沒了 這是因為移入移出的動畫效果導致的 .el-table__body {.el-table__row:hover {background-color: pink !important;}} 更改為后面的代碼&#xff0c;就可以了 .el-table__…

Milvus核心設計(2)-----TSO機制詳解

目錄 背景 動機 Timestamp種類及使用場景 Guarantee timestamp Service timestamp Graceful time Timestamp同步機制 主流程 時間戳同步流程 背景 Milvus 在設計上突出了分布式的設計,雖然Chroma 也支持分布式的store 與 query。但是相對Milvus來說,不算非常突出。…

Windows 32 匯編筆記(一):基礎知識

一、80x86 處理器的工作模式 1.1 實模式 實模式概述 實模式&#xff08;Real Mode&#xff09;是80x86處理器最早支持的工作模式&#xff0c;也是最基礎的工作模式。實模式主要用于早期的MS-DOS操作系統和其他簡單的操作環境。在實模式下&#xff0c;處理器能夠直接訪問1MB的…

Python 神器:wxauto 庫——解鎖微信自動化的無限可能

&#x1f4dd;個人主頁&#x1f339;&#xff1a;誓則盟約 ?收錄專欄?&#xff1a;機器學習 &#x1f921;往期回顧&#x1f921;&#xff1a;“探索機器學習的多面世界&#xff1a;從理論到應用與未來展望” &#x1f339;&#x1f339;期待您的關注 &#x1f339;&#x1f…

mysql高并發設計

mysql高并發設計 一、部署方案 https://blog.csdn.net/weixin_37519752/article/details/138728036 方案1&#xff1a;雙主 1、優點 寫入擴展性&#xff1a;兩個節點都可以處理寫入操作&#xff0c;提高了寫入操作的擴展性。 高可用性&#xff1a;在任一節點故障時&#xff…

數據結構復習計劃之復雜度分析(時間、空間)

第二節&#xff1a;算法 時間復雜度和空間復雜度 算法(Algorithm)&#xff1a;是對特定問題求解方法(步驟)的一種描述&#xff0c;是指令的有限序列&#xff0c;其中每一條指令表示一個或多個操作。 算法可以有三種表示形式&#xff1a; 偽代碼 自然語言 流程圖 算法的五…

貓不吃東西還嘔吐是什么原因?可以預防貓咪嘔吐的主食凍干推薦

貓咪突然食欲不振&#xff0c;還出現了嘔吐的癥狀&#xff0c;這究竟是為什么呢&#xff1f;結合我多年養貓的經驗&#xff0c;讓我們一起分析一下可能的原因。 一、 貓不吃東西還嘔吐是什么原因 &#xff08;1&#xff09;首先、排除貓瘟 如果你的貓咪一直家養&#xff0c;…

【Android】基于 LocationManager 原生實現定位打卡

目錄 前言一、實現效果二、定位原理三、具體實現1. 獲取權限2. 頁面繪制3. 獲取經緯度4. 方法調用5. 坐標轉換6. 距離計算7. 完整代碼 前言 最近公司有個新需求&#xff0c;想要用定位進行考勤打卡&#xff0c;在距離打卡地一定范圍內才可以進行打卡。本文將借鑒 RxTool 的 Rx…

php快速入門

前言 php是一門腳本語言&#xff0c;可以訪問服務器&#xff0c;對數據庫增刪查改&#xff08;后臺/后端語言&#xff09; 后臺語言&#xff1a;php&#xff0c;java&#xff0c;c&#xff0c;c&#xff0c;python等等 注意&#xff1a;php是操作服務器&#xff0c;不能直接在…

QUdpSocket 的bind函數詳解

QUdpSocket 是 Qt 框架中用于處理 UDP 網絡通信的類。bind 函數是此類中的一個重要方法&#xff0c;它用于將 QUdpSocket 對象綁定到一個特定的端口上&#xff0c;以便在該端口上接收 UDP 數據包。 函數原型 在 Qt 中&#xff0c;bind 函數的原型通常如下所示&#xff1a; b…

微軟開源項目GraphRAG——基于知識圖譜的RAG簡介

前言 在大型語言模型&#xff08;LLM&#xff09;的前沿研究中&#xff0c;一個核心挑戰與機遇并存的領域是擴展它們的能力&#xff0c;以解決超出其訓練數據范疇的問題。這不僅要求模型在面對全新數據時仍能保持卓越表現&#xff0c;還意味著開辟了全新的數據分析可能性&…

JVM 堆內存分配過程

設置堆內存大小和 OOM Java 堆用于存儲 Java 對象實例&#xff0c;那么堆的大小在 JVM 啟動的時候就確定了&#xff0c;我們可以通過 -Xmx 和 -Xms 來設定 -Xms 用來表示堆的起始內存&#xff0c;等價于 -XX:InitialHeapSize-Xmx 用來表示堆的最大內存&#xff0c;等價于 -XX…

Hadoop-15-Hive 元數據管理與存儲 Metadata 內嵌模式 本地模式 遠程模式 集群規劃配置 啟動服務 3節點云服務器實測

章節內容 上一節我們完成了&#xff1a; Hive中數據導出&#xff1a;HDFSHQL操作上傳內容至Hive、增刪改查等操作 背景介紹 這里是三臺公網云服務器&#xff0c;每臺 2C4G&#xff0c;搭建一個Hadoop的學習環境&#xff0c;供我學習。 之前已經在 VM 虛擬機上搭建過一次&am…

簡單的基追蹤一維信號降噪方法(MATLAB 2018)

基追蹤法是基于冗余過完備字典下的一種信號稀疏表示方法。該方法具有可提高信號的稀疏性、實現閾值降噪和提高時頻分辨率等優點。基追蹤法采用表示系數的范數作為信號來度量稀疏性&#xff0c;通過最小化l型范數將信號稀疏表示問題定義為一類有約束的極值問題&#xff0c;進而轉…

c++ primer plus 第15章友,異常和其他 15.3.11 有關異常的注意事項

c primer plus 第15章友&#xff0c;異常和其他 15.3.11 有關異常的注意事項 15.3.11 有關異常的注意事項 文章目錄 c primer plus 第15章友&#xff0c;異常和其他 15.3.11 有關異常的注意事項15.3.11 有關異常的注意事項 15.3.11 有關異常的注意事項 從前面關于如何使用異常…

vue實現表單輸入框數字類型校驗功能

vue實現表單輸入框數字類型校驗功能 1. 樣式代碼 <el-form-item label"訂單總價"><el-input size"small" v-model"form.totalPrice" placeholder"請輸入訂單總價 正整數或者2位數小數" input"check(form.totalPric…

SpringSecurity中文文檔(Servlet Authorize HttpServletRequests)

Authorize HttpServletRequests SpringSecurity 允許您在請求級別對授權進行建模。例如&#xff0c;對于 Spring Security&#xff0c;可以說/admin 下的所有頁面都需要一個權限&#xff0c;而其他所有頁面只需要身份驗證。 默認情況下&#xff0c;SpringSecurity 要求對每個…

Umi.js 項目中使用 Web Worker

1.配置 Umi.js 在 Umi.js 中&#xff0c;需要通過配置來擴展 Webpack 的功能。在項目根目錄下修改 config/config.ts 文件&#xff1a; export default defineConfig({chainWebpack(config) {config.module.rule(worker).test(/\.worker\.ts$/).use(worker-loader).loader(wo…

C語言之指針的奧秘(二)

一、數組名的理解 int arr[10]{1,2,3,4,5,6,7,8,9,10}; int *p&arr[0]; 這里使用 &arr[0] 的?式拿到了數組第?個元素的地址&#xff0c;但是其實數組名本來就是地址&#xff0c;而且是數組首元素的地址。如下&#xff1a; 我們發現數組名和數組?元素的地址打印出…

重要文件放u盤還是硬盤?硬盤和u盤哪個適合長期存儲

在數字時代&#xff0c;我們每天都會處理大量的文件。其中&#xff0c;不乏一些對我們而言至關重要的文件&#xff0c;如家庭照片、工作文檔、財務記錄等。面對這些重要文件的存儲問題&#xff0c;我們通常會面臨&#xff1a;“重要文件放U盤還是硬盤”、“硬盤和U盤哪個適合長…