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
- 先给main-body-right动态绑定sitcky的类名,在这个类名下,先设置好固定定位的样式
- 监听store里的滚动距离,如果大于这个距离,就给main-body-right添加sticky这个类名,如果小于就删除这个类名
- 第三步也是最麻烦的,我们需要动态的获取到teamUserRef这个dom距离它的定位父元素的高度,不想写死这个高度。有几个坑踩过了:
- 不能直接在onMounted中获取mainRef距离它最近的定位父元素的高度,因为onMounted是在组件挂载完后执行,注意到,在setup里面,是通过promise发的异步请求,数据还没返回来,这个时候setup已经执行完了,用的是定义的最初的数据就进行了渲染
- 不能直接在then的回调中直接去拿mainRef距离它最近的定位父元素的高度,因为(js单线程),等到数据回来了(事件循环任务队列),执行完then回调后(整个then执行完),再执行的渲染,应该是要等到到渲染完毕,才能获取到这个距离,要放到nextTick里面才行。
- 因为在setup里面有获取专栏和专题这2个数据,也不知道谁先谁后,所以两个地方都写吧
- mainRef刚开始是直接写在BlogItem组件上的,发现拿到的是undefined,是因为vue3需要使用defineExpose把组件需要的东西暴露出来,才能拿到,拿到的也不是dom。我以为拿到的是dom,这是错的!
- 也可以监听BlogItem的finished事件,来获取这个高度,但是触发事件时也必须写在onUpdated里面,
- 下面是执行的打印情况,也可以从中看出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滚动条滚动后元素固定
代码地址:https://gitee.com/zzhua195/easyblog-web-vuee Framework.vue 在这个布局组件中,监听main的滚动事件,获取滚动的距离,将它存入store,以便其它组件能够共享,监听到 <template><div c…...
新吲哚菁绿染料IR-825 NHS,IR825 NHS ester,IR825 SE,IR-825 活性酯,用于科研实验研究和临床
IR825 NHS理论分析:中文名:新吲哚菁绿-琥珀酰亚胺酯,IR-825 琥珀酰亚胺酯,IR-825 活性酯英文名:IR825 NHS,IR-825 NHS,IR825 NHS ester,IR825 SECAS号:N/AIR825 NHS产品详…...
GO语言--接口(interface)的定义及使用
接口定义 接口也是一种数据类型,它代表一组方法的集合。 接口是非侵入式的。即接口设计者无需知道接口被哪些类型实现,而接口使用者只需知道实现怎样的接口,并且无须指明实现哪一个接口。编译器在编译时就会知道哪个类型实现哪个接口&#…...
【Python语言基础】——Python MongoDB 查询
Python语言基础——Python MongoDB 查询 文章目录 Python语言基础——Python MongoDB 查询一、Python MongoDB 查询一、Python MongoDB 查询 筛选结果 在集合中查找文档时,您能够使用 query 对象过滤结果。 find() 方法的第一个参数是 query 对象,用于限定搜索。 实例 查找地…...
第十四届蓝桥杯模拟赛【第三期】Python
1 进制转换 问题描述 请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 0)都为字母(A 到 F)。 请将这个数的十进制形式作为答案提交。 答案:2730 def ch…...
windows 下docker 安装clickhouse
docker 下载https://www.docker.com/products/docker-desktop/将下载下来的Docker Desktop Installer.exe文件双击进行安装即可,安装完成后,任务栏会出现一个蓝色的小鲸鱼图标(注意安装完成后可能会重启系统)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简单介绍
对于一名前端工程师,想要进阶成为全栈工程师,redis技术是我们一定需要掌握的。作为当前非关系型数据库Nosql中比较热门的key-value存储系统,了解redis的原理和开发是极其重要的。本文我会循序渐进的带领大家一步步认识redis,使用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 命令参考官方文档: Understanding services背景 服务(Service&…...
【链表OJ题(五)】合并两个有序链表
📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:数据结构 🎯长路漫漫浩浩,万事皆有期待 文章目录链表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…...
小样本学习
机器学习就是从数据中学习,从而使完成任务的表现越来越好。小样本学习是具有有限监督数据的机器学习。类似的,其他的机器学习定义也都是在机器学习定义的基础上加上不同的限制条件衍生出来。例如,弱监督学习是强调在不完整、不准确、有噪声、…...
python打包成apk界面设计,python打包成安装文件
大家好,给大家分享一下如何将python程序打包成apk文件,很多人还不知道这一点。下面详细解释一下。现在让我们来看看! 1、如何用python制作十分秒加减的apk 如何用python制作十分秒加减的apk?用法:. apk包放入apk文件目录,然后输入…...
pytorch转onnx踩坑日记
在深度学习模型部署时,从pytorch转换onnx的过程中,踩了一些坑。本文总结了这些踩坑记录,希望可以帮助其他人。 首先,简单说明一下pytorch转onnx的意义。在pytorch训练出一个深度学习模型后,需要在TensorRT或者openvin…...
极智AI | GPT4来了,ChatGPT又该升级了
欢迎关注我,获取我的更多经验分享 大家好,我是极智视界,本文介绍一下 GPT4来了,ChatGPT又该升级了,更多的是个人思考。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码下载,链接:https://t.zsxq.com/0aiNxERDq 从 ChatGPT 发布 (2022年11月30日) 到…...
智能优化算法之灰狼优化算法(GWO)的实现(Python附源码)
文章目录一、灰狼优化算法的实现思路1、社会等级结构分级2、包围猎物3、攻击猎物4、搜索猎物二、算法步骤三、实例一、灰狼优化算法的实现思路 灰狼优化算法(Grey Wolf Optimizer,简称GWO)是由Seyedali Mirjalili等人于2014年提出的一种群智…...
leetCode热题10-15 解题代码,思路
前言 计划做一系列算法题的文章,因为自己这块确实比较薄弱,但又很重要!写这篇文章前,我已经刷了一本剑指offer,leetcode top150道,牛客某题库106道 这个样子吧,感觉题量算是入门了吧࿱…...
同步辐射GISAXS和GIWAXS的原理及应用领域
同步辐射GISAXS和GIWAXS是两种常用的同步辐射X射线衍射技术,它们在材料科学、化学、生物学、物理学等领域中广泛应用。本文将从原理、实验方法和应用三个方面,对同步辐射GISAXS和GIWAXS进行描述和比较。 一、原理 GISAXS和GIWAXS都是利用X射线与样品相互…...
OpManager 进行网络性能管理
计算机网络构成了任何组织的 IT 基础架构的支柱。由于企业严重依赖基于互联网的应用程序,由于网络相关问题,最终用户不受影响非常重要。因此,借助网络管理解决方案监控和提高网络性能对于保持企业始终正常运行至关重要。这将确保维护服务级别…...
面试被问到向上转型和向下转型时,怎么回答?
目录 前置小知识 1、向上转型 补充:向上转型的三种情况 2、向下转型 使用关键字:instanceof 3、转型带来了什么好处 前置小知识 java中的继承,我们简单回顾一下 通过java中的继承机制,可以实现一个类继承另一个类ÿ…...
加密月解密:概述,基础篇
加密月解密:概述,基础篇 2022找工作是学历、能力和运气的超强结合体,遇到寒冬,大厂不招人,可能很多算法学生都得去找开发,测开 测开的话,你就得学数据库,sql,oracle&…...
DC-DC升压模块隔离高压稳压电源直流变换器12v24v48v转600V1000V1100V1500V2000V3000V
特点● 效率高达 80%● 2*2英寸标准封装● 单双电压输出● 价格低● 大于600V高压,稳压输出● 工作温度: -40℃~85℃● 阻燃封装,满足UL94-V0 要求● 温度特性好● 可直接焊在PCB 上应用HRB W1~25W 系列模块电源是一种DC-DC升压变换器。该模块电源的输入电压分为&am…...
pandas数据分析(三)
书接pandas数据分析(二) 文章目录DataFrame数据处理与分析处理超市交易数据中的异常值处理超市交易数据中的缺失值处理超市交易数据中的重复值使用数据差分查看员工业绩波动情况使用透视表与交叉表查看业绩汇总数据使用重采样技术按时间段查看员工业绩Da…...
cpu performance profiling
精彩文章分享1. android performanceAndroid 性能分析工具介绍 (qq.com)手机Android存储性能优化架构分析 (qq.com)抖音 Android 性能优化系列:启动优化之理论和工具篇 (qq.com)那些年,我们一起经历过的 Android 系统性能优化 (qq.com)Android卡顿&#…...
vue2启动项目npm run dev报错 Error: Cannot find module ‘babel-preset-es2015‘ 修改以及问题原因
报错内容如下图: 说找不到模块 babel-preset-es2015。 在报错之前,我正在修改代码,使用 ElementUI 的按需引入方式,修改了 babel.config.js 。 注意:vue/cli 脚手架4版本已经使用了 babel7 ,所以项目中…...
*9 set up 注意点
1、set up 执行的时机:beforeCreate 之前执行一次,this 是 undefined 2、set up 的参数: props:值为对象,组件外传递属性,内部声明并且接收属性 context:上下文对象,其内部包含三个…...
linux目录——文件管理
个人简介:云计算网络运维专业人员,了解运维知识,掌握TCP/IP协议,每天分享网络运维知识与技能。座右铭:海不辞水,故能成其大;山不辞石,故能成其高。个人主页:小李会科技的…...
使用new bing简易教程
申请new bing 首先先申请new bing然后等待通过,如下图 申请完,用edge浏览器,若有科学方法,就能在右上角的聊天进行向AI提问 使用插件来进行直接访问New Bing 在edge浏览器中安装一个插件,地址为:Mod…...
idea插件分享 显著提高开发效率
idea插件 Prettier 作用:支持代码格式化(java、js等) 另外支持js内方法跳转和js中ajax请求跳转到java代码里面 下载:Prettier SQL Params Setter 作用:将日志中mapper输出preparing和paramters处理成完整可直接执行…...
鱼台做网站多少钱/php开源建站系统
2016年机器学习领域取得了很多可以铭记在历史中的进展,将其称为”机器学习元年”也并不为过。市场上各大公司都在进行机器学习的研究,即使没有,他们也通过收购各类机器学习初创公司来快速进入这个领域。 阅读全文:http://click.al…...
猪八戒做的网站怎么样/草莓永久地域网名入2022
1、mongodb 使用安全认证时,添加用户使用createUser,具体如下: 定义: 创建一个数据库新用户用db.createUser()方法,如果用户存在则返回一个用户重复错误。 语法: db.createUser(user, writeConcern) …...
杭州亚运村建设指挥部网站/个人怎么开跨境电商店铺
刚开始学习C#的时候就写过了,直接给地址了: 委托、匿名函数、Lambda表达式和事件的学习 委托学习续:Action、Func和Predicate...
绍兴网站制作多少钱/爱站小工具计算器
1. 打开ppt,将即将打印的部分编辑好,再 另存为—>文件格式请选择windows 图元文件,保存好即可! 2.打开word,使用word的宏,编辑这些图片的宏代码: (1) 点击“工具”…...
做网站需要上门服务吗/表白网页制作免费网站制作
0x00 前言 为了练习python,强迫自己能用Python的题都用python解题还有各种密码 0x01 奇怪的字符串 实验吧题目:信息保密的需求和实际操作自古有之,与之相应的信息加密与解密也是历史悠久,现有一段经过古典密码理论(不止…...
免费自制app软件靠谱么/网站搜索优化方法
Nginx默认没有开启利用多核CPU,我们可以通过增加worker_cpu_affinity配置参数来充分利用多核CPU。CPU是任务处理,计算最关键的资源,CPU核越多,性能就越好。配置Nginx多核CPU,worker_cpu_affinity使用方法和范例1. 2核CPU,开启2个进…...