Skip to content
实现左右联动功能
html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="viewport"
        content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>分类</title>
    <link rel="stylesheet" href="https://npm.webcache.cn/vant@3/lib/index.css" />
    <script src="https://npm.webcache.cn/vue@3.5.25/dist/vue.global.js"></script>
    <script src="https://npm.webcache.cn/vant@3/lib/vant.min.js"></script>
</head>

<body>
    <div id="app">
        <van-nav-bar title="测试" left-arrow fixed placeholder z-index="999" :safe-area-inset-top="true"
            @click-left="onClickLeft"></van-nav-bar>
        <div class="box-box">
            <div class="left-nav" id="leftNav">
                <div class="lf-lis" :class="{'selected':nagInd==index}" v-for="(category, index) in categories"
                    :key="index" @click="navigateToCategory(category.id,index)">
                    {{ category.name }}
                </div>
            </div>
            <div class="right-content" id="right-content" ref="rightContent" @scroll="handleScroll">
                <div v-for="(product, index) in products" :key="index" :id="'b'+index" class="ri-box">
                    <div class="ri-lis">
                        <div class="ri_lis-title">------{{ product.name }}------</div>
                        <div class="ri-lis-box">
                            <div class="ri-lis-li" v-for="(item, ind) in product.child" :key="ind">
                                <img class="imgs" :src="`https://develop.dongguanhongyun.com/resources/5903/202405/17168772712541156601615.png`" alt="" />
                                <div class="li_title">{{item.name}}</div>
                            </div>
                        </div>
                    </div>
                </div>
                <!-- 最后一类商品不够时,添加高度撑满屏幕 -->
                <div class="entry-box" v-if="childLth<15"></div>
            </div>
        </div>
    </div>
    <script>
        const app = Vue.createApp({
            data() {
                return {
                    categories: [
                        // 左侧导航栏的选项
                        { id: 1, name: "分类1" },
                        { id: 2, name: "分类2" },
                        { id: 3, name: "分类3" },
                    ],
                    nagInd: 0,
                    products: [
                        // 右侧商品列表的模块
                        {
                            id: "product1",
                            name: "商品1",
                            child: [
                                { id: "product2", name: "商品1-1" },
                                { id: "product2", name: "商品1-2" },
                                { id: "product2", name: "商品1-3" },
                                { id: "product4", name: "商品1-4" },
                                { id: "product5", name: "商品1-5" },
                            ],
                        },
                        {
                            id: "product2",
                            name: "商品2",
                            child: [
                                { id: "product2", name: "商品1-1" },
                                { id: "product2", name: "商品1-2" },
                                { id: "product2", name: "商品1-3" },
                            ],
                        },
                        {
                            id: "product3",
                            name: "商品3",
                            child: [
                                { id: "product1", name: "商品1-1" },
                                { id: "product2", name: "商品1-2" },
                                { id: "product3", name: "商品1-3" },
                                { id: "product4", name: "商品1-4" },
                                { id: "product5", name: "商品1-5" },
                                { id: "product6", name: "商品1-6" },
                                { id: "product6", name: "商品1-7" },
                            ],
                        },
                        // {
                        //   id: "product4",
                        //   name: "商品4",
                        //   child: [
                        //     { id: "product2", name: "商品1-1" },
                        //     { id: "product2", name: "商品1-2" },
                        //     { id: "product2", name: "商品1-3" },
                        //     { id: "product4", name: "商品1-4" },
                        //   ],
                        // },
                    ],
                    childLth: "",
                    hightArr: [], //列表每个分类对应的区域top集合
                    dis_scroll: false,
                };
            },
            created() { },
            mounted() {
                let that = this;
                this.$nextTick(() => {
                    that.infoScroll();
                });
                const leftColumn = document.getElementById("leftNav");
                const rightColumn = this.$refs.rightContent;
                console.log("leftColumn  ----->  ", leftColumn);
                console.log("rightColumn  ----->  ", rightColumn);
                // 监听左侧按钮点击事件
                leftColumn.addEventListener("click", function () {
                    that.dis_scroll = true;
                });
                // 监听右侧滚动事件
                rightColumn.addEventListener("scroll", function (event) {
                    console.log("res1111111  ----->  ", event);
                    // 获取右侧滚动距离
                    const scrolledElement = event.target;
                    const scrollDistance = scrolledElement.scrollTop;
                    // console.log("scrollDistance   ----->  ", scrollDistance);
                    if (!that.dis_scroll) {
                        console.log("右侧触发了滚动事件");
                        // 在这里添加处理右侧滚动事件的逻辑
                        // 设置左侧滚动位置-左右联动
                        // leftColumn.scrollTop = scrollDistance;
                        // 选中状态联动随之改变
                        // if (that.left_scroll) return;
                        that.hightArr.map((item, index) => {
                            if (scrollDistance > item) {
                                that.nagInd = index;
                            }
                        });
                    } else {
                        console.log("左侧触发了滚动事件");
                        that.dis_scroll = false;
                    }
                });
            },
            methods: {
                handleScroll() {
                    console.log(
                        "触底触底触底触底触底触底触底触底触底触底触底触底触底触底触底"
                    );
                    // 在这里处理触底事件的逻辑
                },
                navigateToCategory(categoryId, index) {
                    this.nagInd = index;
                    // console.log(
                    //   "this.$refs.rightContent1111111  ----->  ",
                    //   this.$refs.rightContent.querySelector(`#b${index}`)
                    // );
                    // console.log(
                    //   "this.$refs.rightContent3333333  ----->  ",
                    //   document.getElementById("right-content")
                    // );
                    // 找到对应分类在右侧商品列表中的位置
                    const categoryElement = this.$refs.rightContent.querySelector(
                        `#b${index}`
                    );
                    const rightEle = document.getElementById("right-content");
                    // const categoryElement = document.getElementById(`#b${index}`);//null
                    if (categoryElement) {
                        // 使用滚动或动画效果将页面滑动到对应位置
                        // categoryElement.scrollIntoView({ behavior: "smooth" }); //特别注意坑点-使用后左侧导航栏切换第一次切换有问题
                        rightEle.scrollTop = categoryElement.offsetTop - 44; //减去顶部导航栏高度
                    }
                },
                infoScroll: function () {
                    let that = this;
                    let len = that.products.length;
                    that.childLth = that.products[len - 1].child.length;
                    let height = 0;
                    let hightArr = [];
                    for (let i = 0; i < len; i++) {
                        //获取元素所在位置
                        let idView = "b" + i;
                        // console.log(" idView ----->  ", idView);
                        let query = document.getElementById(idView);
                        // console.log(query, "queryqueryqueryquery");
                        let rect = query.getBoundingClientRect();
                        // console.log(rect, "rectrectrectrectrect");
                        let top = rect.top;
                        hightArr.push(top);
                        that.hightArr = hightArr;
                        // console.log(hightArr, "hightArrhightArr");
                    }
                },
            },
        });
        app.use(vant);
        app.mount("#app");
    </script>
    <style>
        body {
            margin: 0;
            padding: 0;
            background-color: #f7f7f7;
        }

        .van-nav-bar .van-icon {
            color: #000000;
        }

        .van-nav-bar__content {
            background-color: #fff;
            height: 44px;
        }

        .van-hairline--bottom:after {
            border: none;
        }

        div {
            box-sizing: border-box;
        }

        .box-box {
            width: 100%;
            height: calc(100vh - 44px);
            display: flex;
        }

        .left-nav {
            width: 100px;
            height: 100%;
            background-color: #fff;
            overflow-y: auto;
        }

        .lf-lis {
            width: 100%;
            text-align: center;
            height: 50px;
            line-height: 50px;
        }

        .selected {
            color: aqua;
        }

        .right-content {
            flex: 1;
            height: 100%;
            overflow-y: auto;
        }

        .right-content::-webkit-scrollbar {
            display: none;
        }

        .ri_lis-title {
            width: 100%;
            color: #999;
            padding: 20px;
            text-align: center;
        }

        .ri-lis-box {
            width: 100%;
            padding: 10px;
            display: flex;
            flex-wrap: wrap;
        }

        .ri-lis-li {
            margin-right: 10px;
            margin-bottom: 10px;

            &:nth-child(3n) {
                margin-right: 0;
            }
        }

        .imgs {
            width: 80px;
            height: 80px;
            border-radius: 50%;
        }

        .li_title {
            width: 100%;
            text-align: center;
            font-size: 12px;
        }

        .entry-box {
            height: calc(100vh - 100px);
        }
    </style>
</body>

</html>