vue实现跨页面定位锚点区域方式
实际企业项目开发中,如何基于Vue2,利用锚点实现元素区域滚动定位
项目需求
- 点击左菜单,实现右边内容区域滚动定位;
- 管理页,可以预览该页,并根据预览内容的id定位到滚动区域;
需求分析并实现
需求一
点击左菜单,实现右边内容区域滚动定位
1、如果你使用的是ant-design Vue UI库,是可以使用自带的锚点组件的
<template> <!-- 左边菜单区 --> <a-anchor :affix="false" :get-current-anchor="getCurrentAnchor"> <!-- 一级锚点 --> <a-anchor-link href="#menu1" rel="external nofollow" title="菜单一"> <!-- 二级锚点 --> <a-anchor-link href="#menu2" rel="external nofollow" title="菜单二" /> </a-anchor-link> </a-anchor> <!-- 右边内容滚动区 --> <div id="menu1">菜单一的详细内容</div> <div id="menu2">菜单二的详细内容</div> </template> <script> export default { methods: { // 默认高亮的锚点 getCurrentAnchor() { return '#menu1'; }, }, }; </script>
优点:
1、已经封装好的,方便使用
缺点:
1、a-anchor组件,原理是类似:a标签的href属性值(href=“#menu”)和内容区域id属性值(<div id=‘menu’>)一致,实现锚点定位,但是,同时浏览器URL地址会拼接#id,对于Vue开发的项目来说, 如果当前页面地址是 http://localhost:8080/#/since, 你点击锚点:菜单一,路径就会变成: http://localhost:8080/#/menu1, 此时刷新页面页面跳转失败,页面内容丢失
2、缺点二就是无法实现 需求二,无法满足在其他页面 打开该页面,根据内容id实现,内容区域滚动
2、如果使用的是 Element UI, 该UI库对于Vue2,来说是没有锚点相关的组件的,所以需要借助第三方插件 vue-scrollto
1、 npm install --save vue-scrollto 2、 在需要使用锚点的组件中: var VueScrollTo = require('vue-scrollto'); 3、给锚点添加点击事件 var options = { container: '#container', easing: 'ease-in', lazy: false, offset: -60, force: true, cancelable: true, onStart: function(element) { // scrolling started }, onDone: function(element) { // scrolling is done }, onCancel: function() { // scrolling has been interrupted }, x: false, y: true } VueScrollTo.scrollTo(element, duration, options)
缺点:
亲测无效,无法实现,点击左边菜单,右侧内容滚动
看了好多博主,有的需要在router.js路由文件处理,有的需要在组件实例中watch路由(router),好像都没用
需求最终实现
利用scrollIntoView方法,同时实现需求一和需求二
1.实现需求一:点击左菜单,实现右边内容区域滚动定位(监听路由)
// 1、在左菜单点击事件中,实现如下代码 点击左菜单 当前页面路由拼接 search参数(菜单对应的右边内容id) // 2、在锚点页面,监听路由变化 监听路由变化,获取search参数, // 3、设置document.body.scrollTop (document 和 this.$el 都可以) document.body.scrollTop = this.$el.querySelector('#'+search参数).scrollIntoView() // 最终代码 watch: { // 点击左菜单路由可以监听到 但是点击栏目预览 需要走mounted() $route(newRoute) { if (!newRoute.query.programId) return; // 点击锚点 路由监听不到 // console.log(newRoute.params.programId,'newRoute.params.programId') let id = "program" + this.$route.query.programId; this.$nextTick(()=>{ if(this.$el.querySelector(`#${id}`)) { // scrollIntoView 不能随便添加参数 建议不要加任何参数 document.body.scrollTop = this.$el.querySelector(`#${id}`).scrollIntoView(); } }); this.saveCurrentProgramId = newRoute.query.programId; }, },
2.管理页,可以预览该页,并根据预览内容的id定位到滚动区域;(mounted()钩子中实现)
// 1、在锚点页面,mounted()钩子中,获取search参数id this.$router.query.id 监听路由变化,获取search参数, // 2、设置document.body.scrollTop // document 和 this.$el 都可以 document.body.scrollTop = this.$el.querySelector('#'+search参数).scrollIntoView() // 最终代码 mounted() { let that = this; // id选择器不能以数字开头 不能包含 / 等特殊字符 setTimeout(function() { if(that.$route.query.programId) { let id = "program" + that.$route.query.programId; if(that.$el.querySelector(`#${id}`)) { // scrollIntoView 不能随便添加参数 建议不要加任何参数 document.body.scrollTop = that.$el.querySelector(`#${id}`).scrollIntoView(); } } },1000) }
注意:
- scrollIntoView()方法最好不要添加任何参数,加了参数有可能失效
- id选择器千万不能以数字开头,且不能包括 \ 等特殊字符(我为了拼接原先页面的路径和id,将内容区域id熟悉写成:id=‘since/123’),此时会报错:选择器无效
- this.$el后面不能使用getElementId类似方法,只能使用querySelector类似的方法
- 元素渲染时期问题,需要添加定时器和this.$nextTick(()=>()),来操作元素
- 核心代码:document.body.scrollTop = this.$el.querySelector(‘#’+search参数).scrollIntoView()
缺点
在Vue项目中,使用了document对象,虽然需求实现了,但是并不是最好的。如果你们有较好的方法可以评论区回复
题外话:
有的博主写的是:
document.body.scrollTop = this.$el.querySelector(selector).offsetTop
亲测无效!
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
vue3二次封装element-ui中的table组件的过程详解
这篇文章主要给大家介绍了vue3二次封装element-ui中的table组件的过程,文中通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友跟着小编一起来学习吧2024-01-01
最新评论