ref&onscroll
ref官方解释:被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件
使用方法:
通过$refs去获取被注册元素或组件实例/示例:this.$refs.绑定属性.元素属性方法
!使用注意:
ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模板中做数据绑定
通过ref获取子组件的方法/这里是注册到组件上的操作
1. 注册引用
<!-- 父组件 -->
<div class="parent_cpn">
<input type="button" value="使用子组件方法" @click="get_item">
<refItem ref="refItems"></refItem>
</div>
2. 创建子组件,添加事件
<!-- 子组件 -->
<div class="child_cpn">
<button @click="say_hello()">向老大哥问好</button>
</div>
<!-- methods -->
say_hello(val){
val == undefined ? this.say = '大哥好' : this.say = val
log(`来自${val == undefined ? '小老弟' : '老大哥'}的问候:${this.say}`)
}
3. 父组件中使用子组件的方法
<!-- 父组件methods -->
get_item(){
let cont = '好!很有精神'
this.$refs.refItems.say_hello(cont)
}
结果展示
注:不仅仅只能获取子组件的事件,data中的数据也是可以获取的
onscroll
vue中提供的一种监听滚动元素的一个事件。
使用方法:
在元素中绑定事件@scroll,在methods中使用。事件名(e){},这个事件会传递一个事件参数
vue中页面的滚动监听和元素高度获取
获取全局高度
log("页面全文高",document.body.scrollHeight)
log('页面可见高',document.body.offsetHeight)
log('页面可见区域高',document.body.clientHeight)
log('页面当前高',document.documentElement.scrollTop)
log('页面分辨率高',window.screen.height)
log('页面工作区高',window.screen.availHeight)
结果
此处参考地址
使用ref获取元素高度
<div id="box" ref="box"></div> <!-- 首先给一个元素注册引用(此方法非原生) -->
log(this.$refs.box.scrollHeight)//对元素的信息获取并打印
结果
<!-- 获取到的是box的高度 -->
#box{
width: 100%;
height: 5000px;
overflow-y: auto; <!-- y轴自由滚动 -->
}
注:$refs可以获取DOM元素的方法
例如:
<!-- 那么这是对被注册元素的子元素做操作 -->
<!-- html -->
<div id="box" ref="box">
<input type="text" placeholder="hello" value="conts">
</div>
<!-- mounted -->
this.$refs.box.childNodes[0].value = '改变它' <!-- 修改子节点的value值/这里也是$refs获取到的原生方法 -->
效果图/之前
效果图/之后
那么获取到元素或页面的高度能干啥呢?
1. 返回顶部
2. 阅览进度条
3. 锚点跳转(此篇未写)
返回顶部(先使用事件监听实现)
1. 首先有个按钮
<!-- html -->
<button class="go_top" :style="go_top">返回<br />顶部</button>
<!-- vue实例中 -->
data() {
return {
go_top:{
display:'none'
}
}
},
<!-- css -->
.go_top {
position: fixed;
bottom: 3%;
right: 3%;
width: 50px;
height: 50px;
border: 1px solid #CCCCCC;
border-radius: 50%;
color: #565656;
}
2. 滚动显隐
<!-- 监听页面滚动到一定距离显示返回顶部按钮 -->
<!-- 在mounted中启用监听 -->
window.addEventListener('scroll', this.body_scroll)
// 获取页面当前高度(兼容) //记得在组件销毁的时候移除监听以防无谓的监听事件
<!-- body_scroll事件中 -->
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
//当前高度大于1000,显示按钮,否则隐藏按钮
scrollTop >= 1000 ? this.go_top.display = 'block' : this.go_top.display = 'none'
<!-- 移除监听 -->
destroyed() {
window.removeEventListener('scroll', this.body_scroll)
}
3. 点击返回
<!-- 按钮点击事件返回顶部 -->
<!-- html -->
<button class="go_top" :style="go_top" @click="go_tops">返回<br />顶部</button>
<!-- methods -->
go_tops() {
//直接返回
document.documentElement.scrollTop = 0
// 获取页面当前高度(兼容)
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop
const timer = setInterval(() => { //使用定时器设置没n毫秒返回n距离
document.body.scrollTop = document.documentElement.scrollTop = scrollTop -= 50
if(scrollTop <= 0){ //小于0清除定时器
console.log(scrollTop);
clearInterval(timer)
}
},10)
},
至此,返回顶部的功能算是完成了,不过之前使用的是原生的事件监听,对于页面的滚动监听vue中也是提供了监听元素滚动的方法,
<!-- 在要监听的元素上绑定滚动监听事件 -->
<!-- @scroll="u_scroll" -->
<!-- 使用vue提供的onscroll方法显隐返回顶部按钮 -->
u_scroll(e) {
// log(e.srcElement.scrollTop)
let table_src = e.srcElement.scrollTop
e.srcElement.scrollTop >= 1000 ? this.go_top.display = 'block' : this.go_top.display = 'none'
},
<!-- 使用$refs返回顶部 -->
let tabs_hei = this.$refs.tabs.scrollTop
const timer = setInterval(() => {
this.$refs.tabs.scrollTop -= (tabs_hei / 30)
if (this.$refs.tabs.scrollTop <= 0) {
clearInterval(timer)
}
}, 1)
当我们浏览文档的时候,会发现有些文档有进度条的显示,算是一个小功能,利用vue中的scroll也可以很简洁的完成
<!-- html -->
<div class="progress_parent">
<div :style="progress_bar">
</div>
</div>
<!-- data中样式对象 -->
progress_bar:{//阅览进度条
width:'0%',
height:'2px',
backgroundColor:'gold'
}
<!-- scroll方法中 -->
let line_val = init_table <= 0 ? "0%" : (table_src / init_table * 100).toFixed(5) + '%';
log("进度条",line_val);
this.progress_bar.width = line_val
最后贴上所有代码
<template>
<div id="box" class="box" ref="box">
<!-- <input type="text" placeholder="hello" value="conts"> -->
<div class="progress_parent">
<div :style="progress_bar">
</div>
</div>
<div class="scroll_region">
<transition name="btn_style">
<button class="go_top" v-show="go_top_show" @click="go_tops">返回<br />顶部</button>
</transition>
<div class="region_cont" @scroll="u_scroll" ref="tabs">
<table border="1" cellpadding="0" cellspacing="0">
<tr>
<td>姓名</td>
<td>江湖人称</td>
<td>年龄</td>
<td>性别</td>
</tr>
<tr class="tab_items" v-for="(itemU,indexU) in user_info" :key="itemU.id">
<td>{{itemU.name}}</td>
<td>{{itemU.nickname}}</td>
<td>{{itemU.age}}</td>
<td>{{itemU.gender}}</td>
</tr>
</table>
</div>
</div>
<!-- <button class="go_top" :style="go_top" @click="go_tops">返回<br />顶部</button> -->
</div>
</template>
<script>
const {
log
} = console
export default {
data() {
return {
go_top_show: false, //返回顶部按钮样式
user_info: [{
id: 1,
name: '张三',
"nickname": "法外狂徒",
age: 10,
gender: "未知"
},
{
id: 2,
name: '李四',
"nickname": "清风拂吾脸",
age: 11,
gender: "未知"
},
{
id: 3,
name: '王五',
"nickname": "片叶不沾身",
age: 12,
gender: "未知"
},
{
id: 4,
name: '刘六',
"nickname": "腾挪彩云间",
age: 13,
gender: "未知"
},
{
id: 5,
name: '赵七',
"nickname": "千里不留行",
age: 14,
gender: "未知"
},
{
id: 6,
name: '张三',
"nickname": "法外狂徒",
age: 10,
gender: "未知"
},
{
id: 7,
name: '李四',
"nickname": "清风拂吾脸",
age: 11,
gender: "未知"
},
{
id: 8,
name: '王五',
"nickname": "片叶不沾身",
age: 12,
gender: "未知"
},
{
id: 9,
name: '刘六',
"nickname": "腾挪彩云间",
age: 13,
gender: "未知"
},
{
id: 10,
name: '赵七',
"nickname": "千里不留行",
age: 14,
gender: "未知"
},
{
id: 11,
name: '张三',
"nickname": "法外狂徒",
age: 10,
gender: "未知"
},
{
id: 12,
name: '李四',
"nickname": "清风拂吾脸",
age: 11,
gender: "未知"
},
{
id: 13,
name: '王五',
"nickname": "片叶不沾身",
age: 12,
gender: "未知"
},
{
id: 14,
name: '刘六',
"nickname": "腾挪彩云间",
age: 13,
gender: "未知"
},
{
id: 15,
name: '赵七',
"nickname": "千里不留行",
age: 14,
gender: "未知"
},
{
id: 16,
name: '张三',
"nickname": "法外狂徒",
age: 10,
gender: "未知"
},
{
id: 17,
name: '李四',
"nickname": "清风拂吾脸",
age: 11,
gender: "未知"
},
{
id: 18,
name: '王五',
"nickname": "片叶不沾身",
age: 12,
gender: "未知"
},
{
id: 19,
name: '刘六',
"nickname": "腾挪彩云间",
age: 13,
gender: "未知"
},
{
id: 20,
name: '赵七',
"nickname": "千里不留行",
age: 14,
gender: "未知"
},
{
id: 21,
name: '张三',
"nickname": "法外狂徒",
age: 10,
gender: "未知"
},
{
id: 22,
name: '李四',
"nickname": "清风拂吾脸",
age: 11,
gender: "未知"
},
{
id: 23,
name: '王五',
"nickname": "片叶不沾身",
age: 12,
gender: "未知"
},
{
id: 24,
name: '刘六',
"nickname": "腾挪彩云间",
age: 13,
gender: "未知"
},
{
id: 25,
name: '赵七',
"nickname": "千里不留行",
age: 14,
gender: "未知"
},
{
id: 26,
name: '张三',
"nickname": "法外狂徒",
age: 10,
gender: "未知"
},
{
id: 27,
name: '李四',
"nickname": "清风拂吾脸",
age: 11,
gender: "未知"
},
{
id: 28,
name: '王五',
"nickname": "片叶不沾身",
age: 12,
gender: "未知"
},
{
id: 29,
name: '刘六',
"nickname": "腾挪彩云间",
age: 13,
gender: "未知"
},
{
id: 30,
name: '赵七',
"nickname": "千里不留行",
age: 14,
gender: "未知"
}
],
progress_bar: { //阅览进度条
width: '0%',
height: '2px',
backgroundColor: 'gold'
}
}
},
mounted() {
// log("页面全文高", document.body.scrollHeight)
// log('页面可见高', document.body.offsetHeight)
// log('页面可见区域高', document.body.clientHeight)
// log('页面当前高', document.documentElement.scrollTop)
// log('页面分辨率高', window.screen.height)
// log('页面工作区高', window.screen.availHeight)
// this.$refs.box.childNodes[0].value = '改变它'
// log(this.$refs.box.childNodes[0].value) //对元素的信息获取并打印
// window.addEventListener('scroll', this.body_scroll)
},
methods: {
u_scroll(e) {
// log(e.srcElement.scrollTop)
let table_src = e.srcElement.scrollTop //当前位置
e.srcElement.scrollTop >= 1000 ? this.go_top_show = true : this.go_top_show = false
// 初始化总高度 // this.$refs.tabs.scrollHeight e.srcElement.scrollHeight
let init_table = this.$refs.tabs.scrollHeight - 500
log('初始化高度', init_table)
// 计算出当前滚动进度,以百分比方式
let line_val = init_table <= 0 ? "0%" : (table_src / init_table * 100).toFixed(5) + '%';
log("进度条", line_val);
this.progress_bar.width = line_val
},
// body_scroll() {
// // 获取页面当前高度(兼容)
// // let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
// //that.$set(that.go_top,'display','block')
// // scrollTop >= 1000 ? this.go_top_show = true : this.go_top_show = false
// },
go_tops() {
// 获取页面当前高度(兼容)
// let scrollTop = document.documentElement.scrollTop || document.body.scrollTop
// const timer = setInterval(() => { //使用定时器设置没n毫秒返回n距离
// document.body.scrollTop = document.documentElement.scrollTop = scrollTop -= 50
// if(scrollTop <= 0){ //小于0清除定时器
// console.log(scrollTop);
// clearInterval(timer)
// }
// },10)
// 这里使用$refs获取元素的高度返回顶部
let tabs_hei = this.$refs.tabs.scrollTop
const timer = setInterval(() => {
this.$refs.tabs.scrollTop -= (tabs_hei / 30)
if (this.$refs.tabs.scrollTop <= 0) {
clearInterval(timer)
}
}, 1)
}
},
destroyed() {
// window.removeEventListener('scroll', this.body_scroll)
}
}
</script>
<style scoped lang="scss">
* {
margin: 0;
padding: 0;
outline: none;
}
.region_cont::-webkit-scrollbar {
//隐藏滚动条
width: 0 !important;
-ms-overflow-style: none;
overflow: -moz-scrollbars-none;
}
#box {
width: 100%;
height: 98vh;
.progress_parent {
position: fixed;
top: 0;
width: 100%;
}
.scroll_region {
position: relative;
width: 94%;
height: 500px;
margin: 0 auto;
.go_top {
position: absolute;
bottom: 3%;
right: 5%;
width: 50px;
height: 50px;
border: 1px solid #CCCCCC;
border-radius: 50%;
color: #565656;
font-size: 13px;
cursor: pointer;
}
}
.region_cont {
overflow-y: auto;
width: 94%;
margin: 20px auto;
height: 500px;
line-height: 72px;
border: 1px solid rgba(215, 215, 215, 1);
box-shadow: 3px 5px 6px rgba(102, 102, 102, 0.349019607843137);
table {
width: 100%;
height: 100%;
.tab_items:nth-child(even) {
background-color: #e2e2e2;
}
tr {
font-family: "楷体", "";
td {
height: 80px;
}
}
tr:first-child {
text-align: center;
td {
width: 200px;
position: -webkit-sticky; // 兼容性差
position: sticky;
top: 0;
height: 88px !important;
background-color: #FFFFFF;
}
}
}
}
// .go_top {
// position: fixed;
// bottom: 3%;
// right: 3%;
// width: 50px;
// height: 50px;
// border: 1px solid #CCCCCC;
// border-radius: 50%;
// color: #565656;
// font-size: 13px;
// cursor: pointer;
// }
}
.btn_style-enter-active,
.btn_style-leave-active {
transition: all 1s ease
}
.btn_style-enter,
.btn_style-leave-active {
opacity: 0
}
</style>
最后贴张效果图
<!-- 你站在巨人肩上,我脚下车轮滚滚 -->
PS:这里面有个问题,就是元素的高度如果使用80vh的话获取的高度就会因为窗口高度或者电脑的屏幕高度改变而受影响,那么计算出来的百分比值就不一致了,虽然使用了固定高度可以解决,但是又不兼容不同高度.
所以如果有什么好的解决办法的大佬们,希望可以告知在下,多谢了!/抱拳