当前位置: 首页 > news >正文

vue3滚动条滚动后元素固定

代码地址:https://gitee.com/zzhua195/easyblog-web-vuee
在这里插入图片描述

Framework.vue

在这个布局组件中,监听main的滚动事件,获取滚动的距离,将它存入store,以便其它组件能够共享,监听到

<template><div class="header"><div class="header-wrapper"><Header></Header></div></div><div class="main" ref="mainRef"><router-view/><div class="main-footer" v-if="route.fullPath === '/blog' || route.fullPath === '/member'"><div class="content-wrapper"><Footer></Footer></div></div></div>
</template><script setup>import Header from './Header.vue';import Footer from './Footer.vue';import { onMounted,ref } from 'vue';import { useStore } from 'vuex'import store from '@/store';import { useRoute } from 'vue-router'const route = useRoute()const mainRef = ref(null)onMounted(()=>{// console.log(mainRef.value);mainRef.value.addEventListener('scroll',function(){store.commit('updateMainScrollTop',mainRef.value.scrollTop)})})</script><style lang="scss"></style>

Blog.vue

  1. 先给main-body-right动态绑定sitcky的类名,在这个类名下,先设置好固定定位的样式
  2. 监听store里的滚动距离,如果大于这个距离,就给main-body-right添加sticky这个类名,如果小于就删除这个类名
  3. 第三步也是最麻烦的,我们需要动态的获取到teamUserRef这个dom距离它的定位父元素的高度,不想写死这个高度。有几个坑踩过了:
    1. 不能直接在onMounted中获取mainRef距离它最近的定位父元素的高度,因为onMounted是在组件挂载完后执行,注意到,在setup里面,是通过promise发的异步请求,数据还没返回来,这个时候setup已经执行完了,用的是定义的最初的数据就进行了渲染
    2. 不能直接在then的回调中直接去拿mainRef距离它最近的定位父元素的高度,因为(js单线程),等到数据回来了(事件循环任务队列),执行完then回调后(整个then执行完),再执行的渲染,应该是要等到到渲染完毕,才能获取到这个距离,要放到nextTick里面才行。
    3. 因为在setup里面有获取专栏和专题这2个数据,也不知道谁先谁后,所以两个地方都写吧
    4. mainRef刚开始是直接写在BlogItem组件上的,发现拿到的是undefined,是因为vue3需要使用defineExpose把组件需要的东西暴露出来,才能拿到,拿到的也不是dom。我以为拿到的是dom,这是错的!
    5. 也可以监听BlogItem的finished事件,来获取这个高度,但是触发事件时也必须写在onUpdated里面,
    6. 下面是执行的打印情况,也可以从中看出vue它的执行过程,可以看到三个子组件先onMounted了,然后父组件就onMounted了,然后专栏的数据响应回来了,先把回调全部执行完(专栏同步),然后触发子组件更新,updated回调,然后nextTick就执行了,专题也是一样。
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
<template><div class="main-body content-wrapper" :style="{ 'min-height': 'calc(100% - 10px)' }"><div class="main-body-left"><BlogItem :blogInfo="blogInfo" v-for="blogInfo, index in blogDataInfo.list" :key="index" class="blog-info" /><el-pagination background layout="prev, pager, next" style="margin-bottom: 12px;":total="blogDataInfo.totalCount" @current-change="handleCurrentChange" :pageSize="blogDataInfo.pageSize" /></div><div :class="['main-body-right', { 'sticky': isSticky }]"><div><blog-side-item who="zhuanlan" @finished="finishd" title="分类专栏"><ul><li class="li-side-category" v-for="category, index in categoryListInfo" :key="index"><div class="side-category"><img class="avatar" :src="proxy.globalInfo.imageUrl + category.cover" alt=""><router-link :to="'/category/' + category.categoryId"><h2>{{ category.categoryName }}</h2></router-link></div><div class="count"><span>{{ category.blogCount }}篇</span></div></li></ul></blog-side-item></div><div><blog-side-item who="zhuanti"  @finished="finishd"  title="专题"><ul><li class="li-side-category" v-for="special, index in specialInfo.list" :key="index"><div class="side-category"><img class="avatar" :src="proxy.globalInfo.imageUrl + special.cover"><router-link :to="'/special/' + special.categoryId"><h2>{{ special.categoryName }}</h2></router-link></div><div class="count"><span>{{ special.blogCount }}篇</span></div></li></ul></blog-side-item></div><div  style="transition:top 1s;" ref="teamUserRef"><blog-side-item who="team-user" title="博客成员" class="team-user" id="teamUser" ><ul><li v-for="userInfo, index in userListInfo" :key="index" class="user-li"><router-link :to="'/member#user-info-' + userInfo.userId" href="#" class="user-part"><img :src="proxy.globalInfo.imageUrl + userInfo.avatar" alt=""><div class="user-info"><div class="nick-name">{{ userInfo.nickName }}</div><div class="profession">{{ userInfo.profession }}</div></div></router-link><div class="count"><span>{{ userInfo.blogCount }}</span></div></li></ul></blog-side-item></div></div></div>
</template><script setup>
import { ref, reactive, getCurrentInstance, onMounted, onBeforeUnmount, watch, nextTick, onUpdated } from 'vue'
import BlogItem from './BlogItem.vue'
import BlogSideItem from './BlogSideItem.vue';
import Footer from '@/views/Footer.vue';
import { useStore } from 'vuex'
const store = useStore()
const { proxy } = getCurrentInstance()const topLength = ref(500)const api = {loadBlogList: "/view/loadBlogList",loadCategory: "/view/loadCategory",loadUser: "/view/loadTeamUser",loacSpecial: "/view/loadSpecial",
};const blogDataInfo = ref({pageSize: 10,pageNo: 1
})async function loadBlogList() {let result = await proxy.Request({url: api.loadBlogList,params: {pageSize: blogDataInfo.value.pageSize,pageNo: blogDataInfo.value.pageNo}})blogDataInfo.value = result
}
loadBlogList()
function handleCurrentChange(pageNo) {blogDataInfo.value.pageNo = pageNoloadBlogList()
}const categoryListInfo = ref({})
async function loadCategoryList() {let result = await proxy.Request({url: api.loadCategory,params: {pageSize: 5}})categoryListInfo.value = result/* topLength.value = teamUserRef.value.offsetTopconsole.log(teamUserRef.value.offsetTop, 1, '专栏'); */console.log('专栏同步');nextTick(()=>{topLength.value = teamUserRef.value.offsetTopconsole.log(teamUserRef.value.offsetTop, 1, '专栏');})
}
loadCategoryList()const userListInfo = ref([])async function loadUserInfoList() {let result = await proxy.Request({url: api.loadUser,params: {pageSize: 5}})userListInfo.value = result
}
loadUserInfoList()const specialInfo = ref([])async function loadSpecialList() {let result = await proxy.Request({url: api.loacSpecial,params: {pageSize: 3}})specialInfo.value = result/* topLength.value = teamUserRef.value.offsetTopconsole.log(teamUserRef.value.offsetTop, 2, '专题'); */console.log('专题同步');nextTick(()=>{topLength.value = teamUserRef.value.offsetTopconsole.log(teamUserRef.value.offsetTop, 2, '专题'); })
}
loadSpecialList()const isSticky = ref(false)
let val = null
const teamUserRef = ref(null)watch(() => store.state.mainScrollTop, (newVal, oldVal) => {// console.log('监听到: ' + newVal);if (newVal >= topLength.value) {isSticky.value = true} else {isSticky.value = false}
}, { immediate: true })onMounted(()=>{console.log(teamUserRef.value,'Blog.vue组件onMounted');
})function finishd(who) {topLength.value = teamUserRef.value.offsetTopconsole.log(teamUserRef.value.offsetTop, 'finished回调', who);
}onUpdated(()=>{console.log('Blog.vue组件更新了');
})
</script><style lang="scss" scoped>
.li-side-category {height: 52px;display: flex;justify-content: space-between;align-items: center;.count {margin-left: 5px;flex-shrink: 0;}.side-category {flex: 1;/* 开启省略的关键或者使用width:0 */overflow: hidden;display: inline-flex;align-items: center;.avatar {width: 40px;height: 40px;border-radius: 5px;margin-right: 5px;}a {text-overflow: ellipsis;white-space: nowrap;/* white-space属性为nowrap时,不会因为超出容器宽度而发生换行 */overflow: hidden;h2 {font-weight: normal;margin: 0;font-size: 16px;color: #1890ff;display: inline;}}}
}.user-li {padding: 10px 5px;display: flex;justify-content: space-between;align-items: center;.count {flex-shrink: 0;margin-left: 10px;}.user-part {display: inline-flex;align-items: center;flex-grow: 1;overflow: hidden;img {width: 50px;height: 50px;border-radius: 50%;margin-right: 10px;}.user-info {overflow: hidden;.nick-name {font-size: 20px;text-overflow: ellipsis;white-space: nowrap;overflow: hidden;}.profession {text-overflow: ellipsis;white-space: nowrap;overflow: hidden;color: #8d8d8d;font-size: 12px;}}}}.sticky .team-user {position: fixed;top: 90px;
}</style>

BlogItem.vue

<template><div class="side-item"><div class="side-item-top"><div class="title">{{ title }}</div><div class="more"><a href="#" title="更多" class="iconfont icon-gengduo1"></a></div></div><div class="side-item-body"><slot><div class="no-data">暂无数据</div></slot></div></div>
</template><script setup>
import { ref,reactive,onMounted,onUpdated } from 'vue'
const props = defineProps(['title','who'])
const emit  = defineEmits(['finished'])
onMounted(()=>{console.log(props.who, 'onMounted');
})
onUpdated(()=>{console.log(props.who, 'updated');emit('finished',props.who)
})
defineExpose({'halo':'你好吗'
})
</script><style lang="scss">
.side-item {width: 300px;box-sizing: border-box;background-color: #fff;border-radius: 5px;padding: 8px;box-shadow: 0 3px 10px 0px rgb(0 0 0 / 10%);margin-bottom: 10px;.more a {color: #1890ff;font-size: 20px;}.side-item-top {height: 32px;line-height: 32px;display: flex;padding: 0 5px;justify-content: space-between;border-bottom: 1px solid #ddd;}.side-item-body {.no-data {color: #9a9a9a;height: 120px;display: flex;justify-content: center;align-items: center;}}
}
</style>

相关文章:

vue3滚动条滚动后元素固定

代码地址&#xff1a;https://gitee.com/zzhua195/easyblog-web-vuee Framework.vue 在这个布局组件中&#xff0c;监听main的滚动事件&#xff0c;获取滚动的距离&#xff0c;将它存入store&#xff0c;以便其它组件能够共享&#xff0c;监听到 <template><div c…...

新吲哚菁绿染料IR-825 NHS,IR825 NHS ester,IR825 SE,IR-825 活性酯,用于科研实验研究和临床

IR825 NHS理论分析&#xff1a;中文名&#xff1a;新吲哚菁绿-琥珀酰亚胺酯&#xff0c;IR-825 琥珀酰亚胺酯&#xff0c;IR-825 活性酯英文名&#xff1a;IR825 NHS&#xff0c;IR-825 NHS&#xff0c;IR825 NHS ester&#xff0c;IR825 SECAS号&#xff1a;N/AIR825 NHS产品详…...

GO语言--接口(interface)的定义及使用

接口定义 接口也是一种数据类型&#xff0c;它代表一组方法的集合。 接口是非侵入式的。即接口设计者无需知道接口被哪些类型实现&#xff0c;而接口使用者只需知道实现怎样的接口&#xff0c;并且无须指明实现哪一个接口。编译器在编译时就会知道哪个类型实现哪个接口&#…...

【Python语言基础】——Python MongoDB 查询

Python语言基础——Python MongoDB 查询 文章目录 Python语言基础——Python MongoDB 查询一、Python MongoDB 查询一、Python MongoDB 查询 筛选结果 在集合中查找文档时,您能够使用 query 对象过滤结果。 find() 方法的第一个参数是 query 对象,用于限定搜索。 实例 查找地…...

第十四届蓝桥杯模拟赛【第三期】Python

1 进制转换 问题描述   请找到一个大于 2022 的最小数&#xff0c;这个数转换成十六进制之后&#xff0c;所有的数位&#xff08;不含前导 0&#xff09;都为字母&#xff08;A 到 F&#xff09;。   请将这个数的十进制形式作为答案提交。 答案&#xff1a;2730 def ch…...

windows 下docker 安装clickhouse

docker 下载https://www.docker.com/products/docker-desktop/将下载下来的Docker Desktop Installer.exe文件双击进行安装即可&#xff0c;安装完成后&#xff0c;任务栏会出现一个蓝色的小鲸鱼图标&#xff08;注意安装完成后可能会重启系统&#xff09;Docker Desktop如果出…...

【华为OD机试真题 JAVA】TLV编码问题

标题:TLV编码问题 | 时间限制:1秒 | 内存限制:262144K | 语言限制:不限 TLV编码是按TagLengthValue格式进行编码的,一段码流中的信元用tag标识,tag在码流中唯一不重复,length表示信元value的长度,value表示信元的值,码流以某信元的tag开头,tag固定占一个字节,lengt…...

深度学习 Day26——使用Pytorch实现猴痘病识别

深度学习 Day26——使用Pytorch实现猴痘病识别 文章目录深度学习 Day26——使用Pytorch实现猴痘病识别一、前言二、我的环境三、前期工作1、设置GPU导入依赖项2、导入猴痘病数据集3、划分数据集四、构建CNN网络五、训练模型1、设置超参数2、编写训练函数3、编写测试函数4、正式…...

redis简单介绍

对于一名前端工程师&#xff0c;想要进阶成为全栈工程师&#xff0c;redis技术是我们一定需要掌握的。作为当前非关系型数据库Nosql中比较热门的key-value存储系统&#xff0c;了解redis的原理和开发是极其重要的。本文我会循序渐进的带领大家一步步认识redis&#xff0c;使用r…...

Understanding services:理解服务(Service)

文章目录背景1. 准备工作2. ros2 service list 命令3. ros2 service type 命令3.1 ros2 service list -t 命令4. ros2 service find 命令5. ros2 interface show 命令6. ros2 service call 命令参考官方文档&#xff1a; Understanding services背景 服务&#xff08;Service&…...

【链表OJ题(五)】合并两个有序链表

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;数据结构 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录链表OJ题(五)1. 合并…...

C++ Primer第五版_第三章习题答案(1~10)

文章目录练习3.1练习3.2一次读入一行一次读入一个词练习3.3练习3.4大的字符串长度大的字符串练习3.5未隔开的隔开的练习3.6练习3.7练习3.8练习3.9练习3.10练习3.1 使用恰当的using 声明重做 1.4.1节和2.6.2节的练习。 // 1.4.1 #include <iostream>using std::cin; using…...

小样本学习

机器学习就是从数据中学习&#xff0c;从而使完成任务的表现越来越好。小样本学习是具有有限监督数据的机器学习。类似的&#xff0c;其他的机器学习定义也都是在机器学习定义的基础上加上不同的限制条件衍生出来。例如&#xff0c;弱监督学习是强调在不完整、不准确、有噪声、…...

python打包成apk界面设计,python打包成安装文件

大家好&#xff0c;给大家分享一下如何将python程序打包成apk文件&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 1、如何用python制作十分秒加减的apk 如何用python制作十分秒加减的apk&#xff1f;用法:. apk包放入apk文件目录,然后输入…...

pytorch转onnx踩坑日记

在深度学习模型部署时&#xff0c;从pytorch转换onnx的过程中&#xff0c;踩了一些坑。本文总结了这些踩坑记录&#xff0c;希望可以帮助其他人。 首先&#xff0c;简单说明一下pytorch转onnx的意义。在pytorch训练出一个深度学习模型后&#xff0c;需要在TensorRT或者openvin…...

极智AI | GPT4来了,ChatGPT又该升级了

欢迎关注我,获取我的更多经验分享 大家好,我是极智视界,本文介绍一下 GPT4来了,ChatGPT又该升级了,更多的是个人思考。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码下载,链接:https://t.zsxq.com/0aiNxERDq 从 ChatGPT 发布 (2022年11月30日) 到…...

智能优化算法之灰狼优化算法(GWO)的实现(Python附源码)

文章目录一、灰狼优化算法的实现思路1、社会等级结构分级2、包围猎物3、攻击猎物4、搜索猎物二、算法步骤三、实例一、灰狼优化算法的实现思路 灰狼优化算法&#xff08;Grey Wolf Optimizer&#xff0c;简称GWO&#xff09;是由Seyedali Mirjalili等人于2014年提出的一种群智…...

leetCode热题10-15 解题代码,思路

前言 计划做一系列算法题的文章&#xff0c;因为自己这块确实比较薄弱&#xff0c;但又很重要&#xff01;写这篇文章前&#xff0c;我已经刷了一本剑指offer&#xff0c;leetcode top150道&#xff0c;牛客某题库106道 这个样子吧&#xff0c;感觉题量算是入门了吧&#xff1…...

同步辐射GISAXS和GIWAXS的原理及应用领域

同步辐射GISAXS和GIWAXS是两种常用的同步辐射X射线衍射技术&#xff0c;它们在材料科学、化学、生物学、物理学等领域中广泛应用。本文将从原理、实验方法和应用三个方面&#xff0c;对同步辐射GISAXS和GIWAXS进行描述和比较。 一、原理 GISAXS和GIWAXS都是利用X射线与样品相互…...

OpManager 进行网络性能管理

计算机网络构成了任何组织的 IT 基础架构的支柱。由于企业严重依赖基于互联网的应用程序&#xff0c;由于网络相关问题&#xff0c;最终用户不受影响非常重要。因此&#xff0c;借助网络管理解决方案监控和提高网络性能对于保持企业始终正常运行至关重要。这将确保维护服务级别…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

华为OD机试-最短木板长度-二分法(A卷,100分)

此题是一个最大化最小值的典型例题&#xff0c; 因为搜索范围是有界的&#xff0c;上界最大木板长度补充的全部木料长度&#xff0c;下界最小木板长度&#xff1b; 即left0,right10^6; 我们可以设置一个候选值x(mid)&#xff0c;将木板的长度全部都补充到x&#xff0c;如果成功…...

【Veristand】Veristand环境安装教程-Linux RT / Windows

首先声明&#xff0c;此教程是针对Simulink编译模型并导入Veristand中编写的&#xff0c;同时需要注意的是老用户编译可能用的是Veristand Model Framework&#xff0c;那个是历史版本&#xff0c;且NI不会再维护&#xff0c;新版本编译支持为VeriStand Model Generation Suppo…...

海云安高敏捷信创白盒SCAP入选《中国网络安全细分领域产品名录》

近日&#xff0c;嘶吼安全产业研究院发布《中国网络安全细分领域产品名录》&#xff0c;海云安高敏捷信创白盒&#xff08;SCAP&#xff09;成功入选软件供应链安全领域产品名录。 在数字化转型加速的今天&#xff0c;网络安全已成为企业生存与发展的核心基石&#xff0c;为了解…...