参考资料
文档地址:https://uniapp.dcloud.net.cn/component/scroll-view.html
官方给的完整代码
<script>export default {data() {return {scrollTop: 0,old: {scrollTop: 0}}},methods: {upper: function(e) {console.log(e)},lower: function(e) {console.log(e)},scroll: function(e) {console.log(e)this.old.scrollTop = e.detail.scrollTop},goTop: function(e) {// 解决view层不同步的问题this.scrollTop = this.old.scrollTopthis.$nextTick(function() {this.scrollTop = 0});uni.showToast({icon: "none",title: "纵向滚动 scrollTop 值已被修改为 0"})}}}
</script><template><view><view class="uni-padding-wrap uni-common-mt"><view class="uni-title uni-common-mt">Vertical Scroll<text>\n纵向滚动</text></view><view><scroll-view :scroll-top="scrollTop" scroll-y="true" class="scroll-Y" @scrolltoupper="upper"@scrolltolower="lower" @scroll="scroll"><view id="demo1" class="scroll-view-item uni-bg-red">A</view><view id="demo2" class="scroll-view-item uni-bg-green">B</view><view id="demo3" class="scroll-view-item uni-bg-blue">C</view></scroll-view></view><view @tap="goTop" class="uni-link uni-center uni-common-mt">点击这里返回顶部</view><view class="uni-title uni-common-mt">Horizontal Scroll<text>\n横向滚动</text></view><view><scroll-view class="scroll-view_H" scroll-x="true" @scroll="scroll" scroll-left="120"><view id="demo1" class="scroll-view-item_H uni-bg-red">A</view><view id="demo2" class="scroll-view-item_H uni-bg-green">B</view><view id="demo3" class="scroll-view-item_H uni-bg-blue">C</view></scroll-view></view><view class="uni-common-pb"></view></view></view>
</template><style>.scroll-Y {height: 300rpx;}.scroll-view_H {white-space: nowrap;width: 100%;}.scroll-view-item {height: 300rpx;line-height: 300rpx;text-align: center;font-size: 36rpx;}.scroll-view-item_H {display: inline-block;width: 100%;height: 300rpx;line-height: 300rpx;text-align: center;font-size: 36rpx;}
</style>
此时的渲染效果
小目标
这个案例代码比较复杂,需要拆解来看。拆分为垂直滚动和横向滚动两个小案例。
之前代码是基于vue2写的,需要改造为vue3的代码。
先把代码改为vue3的setup语法
之前的代码:
export default {data() {return {scrollTop: 0,old: {scrollTop: 0}}},methods: {upper: function(e) {console.log(e)},lower: function(e) {console.log(e)},scroll: function(e) {console.log(e)this.old.scrollTop = e.detail.scrollTop},goTop: function(e) {// 解决view层不同步的问题this.scrollTop = this.old.scrollTopthis.$nextTick(function() {this.scrollTop = 0});uni.showToast({icon: "none",title: "纵向滚动 scrollTop 值已被修改为 0"})}}}
改造后的代码:
import {ref} from 'vue';const scrollTop = ref(0)const old = ref({scrollTop: 0})function upper(e) {console.log(e)}function lower(e) {console.log(e)}function scroll(e) {console.log(e)old.value.scrollTop = e.detail.scrollTop}function goTop(e) {// 解决view层不同步的问题scrollTop.value = old.value.scrollTopnextTick(function() {scrollTop.value = 0});uni.showToast({icon: "none",title: "纵向滚动 scrollTop 值已被修改为 0"})}
垂直滚动案例
接下来拆分案例,先记录一下此时的完整代码,避免改乱了无法恢复。
<script setup>import {ref} from 'vue';const scrollTop = ref(0)const old = ref({scrollTop: 0})function upper(e) {console.log(e)}function lower(e) {console.log(e)}function scroll(e) {console.log(e)old.value.scrollTop = e.detail.scrollTop}function goTop(e) {// 解决view层不同步的问题scrollTop.value = old.value.scrollTopnextTick(function() {scrollTop.value = 0});uni.showToast({icon: "none",title: "纵向滚动 scrollTop 值已被修改为 0"})}
</script><template><view><view class="uni-padding-wrap uni-common-mt"><view class="uni-title uni-common-mt">Vertical Scroll<text>\n纵向滚动</text></view><view><scroll-view :scroll-top="scrollTop" scroll-y="true" class="scroll-Y" @scrolltoupper="upper"@scrolltolower="lower" @scroll="scroll"><view id="demo1" class="scroll-view-item uni-bg-red">A</view><view id="demo2" class="scroll-view-item uni-bg-green">B</view><view id="demo3" class="scroll-view-item uni-bg-blue">C</view></scroll-view></view><view @tap="goTop" class="uni-link uni-center uni-common-mt">点击这里返回顶部</view><view class="uni-title uni-common-mt">Horizontal Scroll<text>\n横向滚动</text></view><view><scroll-view class="scroll-view_H" scroll-x="true" @scroll="scroll" scroll-left="120"><view id="demo1" class="scroll-view-item_H uni-bg-red">A</view><view id="demo2" class="scroll-view-item_H uni-bg-green">B</view><view id="demo3" class="scroll-view-item_H uni-bg-blue">C</view></scroll-view></view><view class="uni-common-pb"></view></view></view>
</template><style>.scroll-Y {height: 300rpx;}.scroll-view_H {white-space: nowrap;width: 100%;}.scroll-view-item {height: 300rpx;line-height: 300rpx;text-align: center;font-size: 36rpx;}.scroll-view-item_H {display: inline-block;width: 100%;height: 300rpx;line-height: 300rpx;text-align: center;font-size: 36rpx;}
</style>
接着移除水平滚动相关的代码,移除后得到的代码如下:
<template><view><view class="uni-padding-wrap uni-common-mt"><view class="uni-title uni-common-mt">Vertical Scroll<text>\n纵向滚动</text></view><view><scroll-view :scroll-top="scrollTop" scroll-y="true" class="scroll-Y" @scrolltoupper="upper"@scrolltolower="lower" @scroll="scroll"><view id="demo1" class="scroll-view-item uni-bg-red">A</view><view id="demo2" class="scroll-view-item uni-bg-green">B</view><view id="demo3" class="scroll-view-item uni-bg-blue">C</view></scroll-view></view><view @tap="goTop" class="uni-link uni-center uni-common-mt">点击这里返回顶部</view><view class="uni-common-pb"></view></view></view>
</template>
这里发现了另一个一个比较细节的知识点,就是回到顶部的功能。先分析回到顶部的功能。
回到顶部的功能
HTML代码如下:
<view @tap="goTop" class="uni-link uni-center uni-common-mt">点击这里返回顶部</view>
js代码如下:
async function goTop(e) {// 解决view层不同步的问题scrollTop.value = old.value.scrollTopawait nextTick(function() {scrollTop.value = 0});uni.showToast({icon: "none",title: "纵向滚动 scrollTop 值已被修改为 0"})}
注意,这个函数是异步的,因为nextTick是一个异步方法,需要使用await。
这个方法是从vue引入的:
import {ref,nextTick,} from 'vue';
回到顶部的功能是如何生效的?
经过测试, 我现在垂直滚动到了C:
然后我点击返回顶部:
可以发现,垂直滚动的位置又回到了A。
不过我们在学习的时候,应该先学习垂直滚动是如何实现的,再学习如何实现回到顶部的功能。
继续分析如何实现垂直滚动
核心的HTML代码如下:
<scroll-view
:scroll-top="scrollTop"
scroll-y="true"
class="scroll-Y"
@scrolltoupper="upper"@scrolltolower="lower" @scroll="scroll"><view id="demo1" class="scroll-view-item uni-bg-red">A</view><view id="demo2" class="scroll-view-item uni-bg-green">B</view><view id="demo3" class="scroll-view-item uni-bg-blue">C</view>
</scroll-view>
代码分析:
- 首先组件使用了scroll-view
- 动态绑定了一个值,这个值记录的是滚动的顶部的位置
:scroll-top="scrollTop"
,这个值的初始值为0,在js中定义如下const scrollTop = ref(0)
- 这个属性
scroll-y="true"
是最关键的,将滚动方向设置成了垂直方向 - 通过
class="scroll-Y"
样式,给容器设置了一个固定高度height: 300rpx;
,因为父盒子的高度是固定的,而内容的高度超过了父元素的限制,所以就出现了滚动的效果 @scrolltoupper="upper"
经过官方文档的解释,滚动到顶部/左边,会触发 scrolltoupper 事件
,因为我们是垂直滚动的,不会滚动到左边,所以,当我们滚动到最顶部的时候,会触发这个事件@scrolltolower="lower"
这个就是滚动到最底部的时候触发的事件了@scroll="scroll"
这个是只要滚动,就会产生的事件<view id="demo1" class="scroll-view-item uni-bg-red">A</view>
内容就比较简单了,核心的地方在于每个内容item的高度都和父元素的高度一样height: 300rpx;
所以得出的结论如下:
- 使用
scroll-view
能够得到一个滚动的容器 - 设置
scroll-y="true"
可以实现垂直滚动 - 将父元素的高度和每个子元素的高度都设置为相同的高度,会产生类似于整个屏幕滚动的效果
如何实现水平滚动
核心代码如下:
<scroll-view class="scroll-view_H" scroll-x="true" @scroll="scroll" scroll-left="120"><view id="demo1" class="scroll-view-item_H uni-bg-red">A</view><view id="demo2" class="scroll-view-item_H uni-bg-green">B</view><view id="demo3" class="scroll-view-item_H uni-bg-blue">C</view>
</scroll-view>
可以发现,和水平滚动类似,只不过通过 scroll-x="true"
设置了水平滚动。
scroll-left="120"
经过官方文档解释,是在设置滚动条的位置。
实现垂直滚动的完整代码
<script setup>import {ref,nextTick,} from 'vue';const scrollTop = ref(0)const old = ref({scrollTop: 0})function upper(e) {console.log(e)}function lower(e) {console.log(e)}function scroll(e) {console.log(e)old.value.scrollTop = e.detail.scrollTop}async function goTop(e) {// 解决view层不同步的问题scrollTop.value = old.value.scrollTopawait nextTick(function() {scrollTop.value = 0});uni.showToast({icon: "none",title: "纵向滚动 scrollTop 值已被修改为 0"})}
</script><template><view><view class="uni-padding-wrap uni-common-mt"><view class="uni-title uni-common-mt">Vertical Scroll<text>\n纵向滚动</text></view><view><scroll-view :scroll-top="scrollTop" scroll-y="true" class="scroll-Y" @scrolltoupper="upper"@scrolltolower="lower" @scroll="scroll"><view id="demo1" class="scroll-view-item uni-bg-red">A</view><view id="demo2" class="scroll-view-item uni-bg-green">B</view><view id="demo3" class="scroll-view-item uni-bg-blue">C</view></scroll-view></view><view @tap="goTop" class="uni-link uni-center uni-common-mt">点击这里返回顶部</view><view class="uni-common-pb"></view></view></view>
</template><style>.scroll-Y {height: 300rpx;}.scroll-view_H {white-space: nowrap;width: 100%;}.scroll-view-item {height: 300rpx;line-height: 300rpx;text-align: center;font-size: 36rpx;}.scroll-view-item_H {display: inline-block;width: 100%;height: 300rpx;line-height: 300rpx;text-align: center;font-size: 36rpx;}
</style>
设置水平滚动的完整代码
<script setup>import {ref,nextTick,} from 'vue';const scrollTop = ref(0)const old = ref({scrollTop: 0})function upper(e) {console.log(e)}function lower(e) {console.log(e)}function scroll(e) {console.log(e)old.value.scrollTop = e.detail.scrollTop}async function goTop(e) {// 解决view层不同步的问题scrollTop.value = old.value.scrollTopawait nextTick(function() {scrollTop.value = 0});uni.showToast({icon: "none",title: "纵向滚动 scrollTop 值已被修改为 0"})}
</script><template><view><scroll-view class="scroll-view_H" scroll-x="true" @scroll="scroll" scroll-left="120"><view id="demo1" class="scroll-view-item_H uni-bg-red">A</view><view id="demo2" class="scroll-view-item_H uni-bg-green">B</view><view id="demo3" class="scroll-view-item_H uni-bg-blue">C</view></scroll-view></view>
</template><style>.scroll-Y {height: 300rpx;}.scroll-view_H {white-space: nowrap;width: 100%;}.scroll-view-item {height: 300rpx;line-height: 300rpx;text-align: center;font-size: 36rpx;}.scroll-view-item_H {display: inline-block;width: 100%;height: 300rpx;line-height: 300rpx;text-align: center;font-size: 36rpx;}
</style>