【锚点】自制锚点 可绑定在任意元素上

最常用的锚点:利用a标签
但更多的情况是,导航栏样式复杂,不适合使用a标签。本文使用 li 标签,同理也可以绑定在 div 等元素上

a标签锚点 (复习part)

<body>
    <nav>
        <a href="#1">锚点1</a>
        <a href="#2">锚点2</a>
    </nav>
    <main>
        <div id="1">内容1</div>
        <div id="2">内容2</div>
    </main>
</body>

解释:a标签的href内容,绑定对应的id值

<!--样式参考-->
nav{
    width: 140px;
    height: 100%;
    position: fixed;
}
nav a{
    display: block;
}
main{
	position: fixed;
    left: 140px;
    height: 100%;
    width: 100%;
    overflow: auto;
}

任意标签锚点

使用dom原生操作方法 scrollIntoView

  • 易懂版

<body>
    <nav>
        <ul>
            <li class="active" name="A">锚点A</li>
            <li name="B">锚点B</li>
            <li name="C">锚点C</li>
            <li name="D">锚点D</li>
            <li name="E">锚点E</li>
            <li name="F">锚点F</li>
        </ul>
    </nav>
    <header></header>
    <main>
        <div class="module" id="A">
            <span></span><span>内容A</span>
        </div>
        <div class="module" id="B">
            <span></span><span>内容B</span>
        </div>
        <div class="module" id="C">
            <span></span><span>内容C</span>
        </div>
        <div class="module" id="D">
            <span></span><span>内容D</span>
        </div>
        <div class="module" id="E">
            <span></span><span>内容E</span>
        </div>
        <div class="module" id="F">
            <span></span><span>内容F</span>
        </div>
    </main>
</body>

重点: 锚点操作

<script>
    // 点击锚点
    $('nav li').on('click',function(){
    //高亮状态更新
    $('nav li.active').removeClass('active');
    $(this).addClass('active');
    //对应dom 移动到最上方 
    //scrollIntoView(),参数可空,这里的 behavior: "smooth" 是缓慢移动
    //**注意这个方法只是原生dom的操作方法,jquery不能用**
    document.getElementById($(this).attr("name")).scrollIntoView({ behavior: "smooth" });
    })
</script>
<!--样式参考-->
body,ul,li{
    margin: 0;
    padding: 0;
}
nav{
    top: 49px;
    left: 0px;
    height: calc(100% - 49px);
    z-index: 999;
    position: absolute;
    background-color: rgb(58, 65, 85);
    text-align: center;
    width: 180px;
}
nav ul{
    margin-top: 14px;
    list-style: none;
}
nav ul li{
    width: 122px;
    height: 14px;
    cursor: pointer;
    font-size: 14px;
    padding: 17px 0px;
    margin-bottom: 8px;
    padding-left: 30px;
    color: rgba(255, 255, 255, 0.7);
    list-style: none;
}
nav ul li:hover{
    opacity: 1;
    color: white;
}
nav ul li.active{
    opacity: 1;
    color: white;
    background: linear-gradient(90deg, rgba(86, 115, 255, 0) 0%, #5673FF 56%, rgba(86, 115, 255, 0) 100%);
}
header{
    width: 100%;
    height: 30px;
    padding: 9px 0px;
    border-bottom: 1px solid #697088;
    background-image: linear-gradient(-180deg, #171F36 0%, #222B46 100%);
}
main{
    margin-left: 240px;
    width: calc(100% - 240px);
    position: absolute;
    overflow: auto;
    height: calc(100% - 50px);
}
main>div{
    font-size: 18px;
    font-weight: bold;
    padding: 30px 0;
    height: 400px;
}
main>div span:first-child{
    width:10px;
    height:10px;
    border-radius:50%;
    background: #5673FF;
    margin-right:12px;
    display:inline-block;
}

这里给 ul 和 li 设置 margin: 0; padding: 0;,是为了li能够居中显示

  • 精简版

<body>
    <nav></nav>
    <header></header>
    <main></main>
</body>
    $(function(){
        //初始化页面
        let anchorHtml = '<ul>';
        let moduleHtml = '';
        for(let i=0;i<7;i++){
            anchorHtml += `<li ${i==0?' class="active" ':''}>锚点${String.fromCharCode(65+i)}</li>`;
            moduleHtml += `<div class="module"><span></span><span>内容${String.fromCharCode(65+i)}</span></div>`
        }
        anchorHtml+='</ul>';
        $('nav').html(anchorHtml);
        $('main').html(moduleHtml);

        // 锚点 点击事件
        $('nav li').on('click',function(){
        $('nav li.active').removeClass('active');
        $(this).addClass('active');
        document.getElementsByClassName("module")[$(this).index()].scrollIntoView({ behavior: "smooth" });
        })
    })

附加:锚点随页面滚动更新高亮状态

重点: 锚点 双向绑定

<script>
    // 点击锚点 
    $('nav li').on('click',function(){
        $('nav li.active').removeClass('active');
        $(this).addClass('active');
    	document.getElementsByClassName("module")[$(this).index()].scrollIntoView({ behavior: "smooth" });
    })
    //页面滚动,锚点随页面滚动更新高亮状态
    var modules=$(".module");
    $('main').scroll(function () {
        for (var i = 0; i < modules.length-1 ; i++) {
            if($(this).scrollTop()<modules[i+1].offsetTop){  //遍历 计算该dom到容器顶端的高度
                $("nav li").eq(i).addClass("active").siblings("li").removeClass("active");
                break;
            }
    	}
    })
</script>

附加:scrollview中停止滚动的监听

在 dom.scrollIntoView({ behavior: “smooth” }) 时,如果 scroll 监听同时存在的话,会出现锚点的高亮异常变跳动或停在非点击行的情况。

因为 scrollIntoView 没有开始和结束的标志,所以采用手动开关 scroll 监听

// 点击锚点 
$('nav li').on('click',function(){
   	$('nav li.active').removeClass('active');
   	$(this).addClass('active');
   	$('main').off('scroll'); //*在scrollIntoView之前关闭监听
	document.getElementsByClassName("module")[$(this).index()].scrollIntoView({ behavior: "smooth" });
	window.setTimeout(function(){main_body_scroll()},3000) //*在结束之后重新打开监听。(一般3s足够了,若内容过长,也可适当增加)
})
main_body_scroll();  //初始化scroll监听

function main_body_scroll(){
    var modules=$(".module");
    $('main').scroll(function () {
        for (var i = 0; i < modules.length-1 ; i++) {
            if($(this).scrollTop()<modules[i+1].offsetTop){  //遍历 计算该dom到容器顶端的高度
                $("nav li").eq(i).addClass("active").siblings("li").removeClass("active");
                break;
            }
    	}
    })
}

附加:目标元素滚动到容器最上方 而不是整个页面最顶处

在使用锚点时,默认滚动到网页最顶处,而一般页面最上方都有标题

📍适用于a标签锚点和任意标签锚点
解决方案:将该容器设置成 position: absolute; height: calc(100% - 50px); overflow: auto;或者 position: fixed; height:100%; overflow: auto;(position设置成absolute或者fixed都可以,主要是为了设置高度 重点:height一定要设置且不能超过页面总高度,尤其是在position设置成absolute时,不然页面也会出滚动条,导致锚点计算出问题



有任何问题,欢迎评论交流!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 2中,可以使用`v-model`指令实现双向数据绑定。对于锚点(即页面上的锚点链接),可以通过绑定`window.location.hash`属性来实现双向绑定。 首先,在Vue实例中定义一个数据属性来存储当前的锚点值,比如`currentAnchor`。然后,在锚点链接中,使用`v-bind:href`指令将锚点绑定到`window.location.hash`。同时,在锚点链接上监听`click`事件,当点击时更新`currentAnchor`的值。 下面是一个示例代码: ```html <div id="app"> <ul> <li v-for="anchor in anchors" :key="anchor"> <a :href="'#' + anchor" @click="updateAnchor(anchor)">{{ anchor }}</a> </li> </ul> <div> <input type="text" v-model="currentAnchor"> </div> </div> <script> new Vue({ el: "#app", data: { currentAnchor: '', anchors: ['anchor1', 'anchor2', 'anchor3'] }, mounted() { window.addEventListener('hashchange', this.updateCurrentAnchor); this.updateCurrentAnchor(); }, destroyed() { window.removeEventListener('hashchange', this.updateCurrentAnchor); }, methods: { updateAnchor(newAnchor) { this.currentAnchor = newAnchor; }, updateCurrentAnchor() { this.currentAnchor = window.location.hash.slice(1); } } }); </script> ``` 在上述代码中,`anchors`数组存储了需要添加锚点的值,通过`v-for`指令遍历生成锚点链接。当点击链接时,会调用`updateAnchor`方法更新`currentAnchor`的值。同时,通过监听`window`对象的`hashchange`事件,调用`updateCurrentAnchor`方法来更新`currentAnchor`的值。 这样,输入框中的值与页面上的锚点链接的值就实现了双向绑定。当修改输入框中的值时,锚点链接也会相应地更新;当点击锚点链接时,输入框中的值也会更新。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值