vue获取子组件高度

this.loopHeight = this.$refs["vueHeader"].$refs["getHeader"].offsetHeight

同理也可以获得子组件的数据和方法。

 

需求描述

就是官网的一个二级页内(锚点)导航,位置在轮播图下方。

需要在轮播图看不见后,自动贴着一级导航(固定定位 position: fixed),固定定位在页头一级导航下面。

然后能看见轮播图的时候,二级导航还要下来,回到原位置,即取消固定定位。(position: static;)。

二级页内导航的下面,是高度不一的 part ,需要实现页面滚动到其对应部分内容可视的时候,对应的高亮二级导航样式。

项目背景

导航和轮播图都是 vue 子组件。

一级导航本身有监听页面滚动,是为了实现底色(背景色)的渐变。

 

代码

父组件

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <title></title>
    <link href="css/common.css" rel="stylesheet">
    <link href="css/swiper.min.css" rel="stylesheet">
    <script src="js/vue.js"></script>
    <script src="js/polyfill.min.js"></script>
    <script src="js/vueComponents.js"></script>
    <style>
        div.navigation{
            width: 100%;
            height:75px;
            line-height:75px;
            box-sizing: border-box;
            background: #fff;
            color: #333;
            border-bottom: 1px solid #d2d2d2;
        }
        .p-static{
            position: static;
        }
        .p-fixed{
            position: fixed;
            top:64px;
            z-index: 2;
        }
        a.nav2{
            display:block;
            width:240px;
            position: relative;
            margin-right:19px;
            margin-left:19px;
            box-sizing: border-box;
            color: inherit;
            font-weight: bold;
            font-size: 15px;
            text-align: center;
            text-decoration: none;
        }
        .navigation a:after {
            content: "";
            display: inline-block;
            width: 1px;
            height: 40px;
            background: #d2d2d2;
            position: absolute;
            top: 20px;
            right: 0;
        }
        .navigation a:last-child:after{
            background: #fff;
        }
        .active{
            border-bottom: 5px solid #afd334;
        }
        div.part a{
            display:block;
            width: 100%;
            height: 100%;
            position: relative;
            top: -139px;
        }

        div.part:target{
            padding-top:139px;
        }
    </style>
</head>
<body>
<div id="root">
    <vue-navbar></vue-navbar>

    <vue-header ref="vueHeader"></vue-header>

    <div class="navigation flex-box" :class=" positionType ? 'p-static' : 'p-fixed'">
        <a class="nav2 parent1" href="#p1" @click="lighten($event)">行业痛点</a>
        <a class="nav2 parent2" href="#p2" @click="lighten($event)">投资收益</a>
        <a class="nav2 parent3" href="#p3" @click="lighten($event)">招募合伙人</a>
        <a class="nav2 parent4" href="#p4" @click="lighten($event)">产品售前/售后服务</a>
    </div>

    <div class="part" id="p1" data-parent="parent1"><img src="img/attract/1.jpg" alt="图片"/></div>
    <div class="part" id="p2" data-parent="parent2"><img src="img/attract/2.jpg" alt="图片"/></div>
    <div class="part" id="p3" data-parent="parent3"><img src="img/attract/3.jpg" alt="图片"/></div>
    <div class="part" id="p4" data-parent="parent4"><img src="img/attract/4.jpg" alt="图片"/></div>

    <img src="img/attract/5.jpg" alt="图片"/>

    <vue-footer></vue-footer>
</div>

<script src="js/jquery-3.1.1.min.js"></script>
<script src="js/swiper.min.js"></script>

<script>
    new Vue({
        el: "#root",
        data: {
            positionType:true,
            loopHeight:100
        },
        methods: {
            lighten: function (event) {
                $(event.target).addClass("active").siblings().removeClass("active");
            },
            handleScroll2: function () {
                var windowHeight = $(window).height();  //窗口高度
                let windowsScrollTop = $(window).scrollTop();//距离顶部滚动
                let windowsScrollTop2 = $(window).scrollTop() + 139;//距离顶部滚动 偏移一级导航+二级导航的高度共139
                this.handleNav1(windowHeight,windowsScrollTop);
                this.handleNav2(windowsScrollTop2);
            },
            handleNav1: function (windowHeight,windowsScrollTop) {
                //当轮播不在可视区域时,将二级导航固定定位 fixed ,如轮播在可视区域,则取消固定定位。
                let val = this.loopHeight - windowsScrollTop;
                if (val < windowHeight && val > 0 ){
                    //轮播在可视区域
                    this.positionType=true;
                }else{
                    //todo:有时二级页内导航下不去(定位不能回复static)positionType 一直是false
                    this.positionType=false;
                }
            },
            handleNav2: function (windowsScrollTop) {
                //二级导航的高亮问题 随页面滚动 当哪部分的内容可视,则将其对应的二级导航样式高亮
                var dataAnimateEl = $('[data-parent]');
                dataAnimateEl.each(function(){
                    let eleHeight = Math.floor($(this).height());//元素自身高度
                    var partEle = $(this);
                    let parent = partEle.attr("data-parent");
                    var pHeight = $(partEle).offset().top;//元素到顶部的高度
                    let maxHeight = pHeight + eleHeight;
                    if ( windowsScrollTop > pHeight && windowsScrollTop < maxHeight) {
                        //目标元素在可视区域
                        $("."+parent).addClass("active").siblings().removeClass("active");
                    }
                });
            }
        },
        mounted: function () {
            //导航偏移 一级导航高度64
            this.loopHeight = this.$refs["vueHeader"].$refs["getHeader"].offsetHeight - 64;//轮播图的高度
            window.addEventListener('scroll', this.handleScroll2);
        }
    })
</script>
</body>
</html>

子组件

Vue.component('vue-navbar', {
    data: function () {
        return {
            showNavbarItem:1,//默认第一项 首页 高亮
            opacity_num: 1//导航透明度默认为0.1
        }
    },
    methods: {
        showNavbar: function (index){
            if(index){
                sessionStorage.setItem("showNavbarItem",index);
                this.showNavbarItem = index
            }else{
                this.showNavbarItem = sessionStorage.getItem("showNavbarItem");
            }
        },
        handleScroll: function () {
            //随页面滚动距离 导航底色逐渐加深
            this.winPos = $(window).scrollTop();//距离顶部滚动高度
            if (this.winPos == 0) {
                this.opacity_num = 1
            } else if (this.winPos > 0 && this.winPos < 200 ) {
                this.opacity_num = 3
            } else if (this.winPos >= 200 && this.winPos < 300 ) {
                this.opacity_num = 6
            } else if (this.winPos >= 300) {
                this.opacity_num = 10
            }
        }
    },
    mounted: function () {
        window.addEventListener('scroll', this.handleScroll);
        this.showNavbar();
    },
    template:`<div class="navbar" :class="'bg_opacity_'+opacity_num"><div class="logo"><img src="img/logo.png" alt="logo"></div><div class="nav" @click="showNavbar(1)"><a :class="showNavbarItem == 1 ? 'navbar-item-active' : ''" href="index.html">首页</a></div><div class="nav" @click="showNavbar(2)"><a :class="showNavbarItem == 2 ? 'navbar-item-active' : ''" href="about.html">关于我们</a></div><div class="nav" @click="showNavbar(3)"><a :class="showNavbarItem == 3 ? 'navbar-item-active' : ''" href="product.html">产品展示</a></div><div class="nav" @click="showNavbar(4)"><a :class="showNavbarItem == 4 ? 'navbar-item-active' : ''" href="cooperation.html">合作案例</a></div><div class="nav" @click="showNavbar(5)"><a :class="showNavbarItem == 5 ? 'navbar-item-active' : ''" href="attract.html">招商加盟</a></div><div class="nav" @click="showNavbar(6)"><a :class="showNavbarItem == 6 ? 'navbar-item-active' : ''" href="solution.html">解决方案</a></div></div>`
})

Vue.component('vue-header', {
    data: function () {
        return {

        }
    },
    template: `<div class="header" ref="getHeader"><div id="index-swiper" class="swiper-container"><div class="swiper-wrapper"><div class="swiper-slide"><img alt="loop-img" src="img/loop/1.jpg"></div><div class="swiper-slide"><img alt="loop-img" src="img/loop/2.jpg"></div><div class="swiper-slide"><img alt="loop-img" src="img/loop/3.jpg"></div></div><div class="swiper-button-prev"></div><div class="swiper-button-next"></div></div></div>`,
    mounted: function () {
        //轮播
        var indexSwiper = new Swiper('#index-swiper', {
            slidesPerView: 1,
            loop: true,
            autoplay:true,
            spaceBetween: 0,
            navigation: {
                nextEl: '.swiper-button-next',
                prevEl: '.swiper-button-prev'
            }
        });

        //鼠标覆盖停止自动切换
//            indexSwiper.el.onmouseover = function () {
//                indexSwiper.autoplay.stop();
//            };
//
//            indexSwiper.el.onmouseout = function () {
//                indexSwiper.autoplay.start();
//            }
    }
})

Vue.component('vue-footer', {
    data: function () {
        return {

        }
    },
    template: '<div class="footer"><img src="img/footer.jpg" alt="img"></div>'
})


 

总结

 

Logo

前往低代码交流专区

更多推荐