首先页面上必须有两个大盒子,里边的盒子背景颜色都设置成一致的
在父级的盒子上必须设置height:100vh;weight:100%,还有固定定位,必须是这种布局的情况下才会解决,例如:
.searchL { width: 100%; height: 100vh; position: fixed; overflow-y: auto; background-color: #fff; }
在子级那个盒子设置高度必须撑出来一点
.search { width: 100%; height: calc(100vh + 5px); background-color: #fff; }
移动端禁止缩放,在public/index.html中设置
<meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no,minimum-scale=1.0,maximum-scale=1.0" />
首先要先获取input框,先要引入ref
import { ref } from 'vue'
const input = ref<HTMLInputElement>()
整个页面滚动所以要先获取整个页面
const searchPage = ref<HTMLDivElement>()
然后在页面加载完成以后执行以下内容,所以要先引入onMounted,先绑定一个ontouchstart事件,手指刚按下的时候执行FnStart里边的代码,然后先获取到手指刚开始按下的位置,然后手指移动的时候再执行FnMove里边代码,用手指滑动的位置 - 刚开始手指按下时获取的位置 然后再判断一下是否 >= 1; 用Math.abs()取绝对值,让这个 绝对值 >= 1 的时候让input框失去焦点
刚开始的时候往下滑不会滑动,因为刚开始的时候是下边滚动,上边的滚动值为0;所以要在刚开始的时候设置一个滚动的值;最后就解决了这个问题
代码如下:
import { onMounted } from 'vue'
interface iStart {
startX: number
x: number
}
const start: iStart = {
startX: 0,
x: 0
}
const Fnmove = (ev: TouchEvent) => {
start.x = ev.changedTouches[0].pageY - start.startX
if (Math.abs(start.x) >= 1) {
input.value!.blur()
}
}
const FnStart = (ev: TouchEvent) => {
start.startX = ev.changedTouches[0].pageY
searchPage.value!.scrollTop = 2
document.ontouchmove = Fnmove
}
onMounted(() => {
searchPage.value!.ontouchstart = FnStart
})
页面完整代码如下:
<template>
<div class="searchL" ref="searchPage">
<div class="search">
<div class="top">
<img src="../assets/pinduoduo/left.jpg" alt="" srcset="" class="top_left" />
<div class="top_search">
<div class="top_shop">
商品
<img src="../assets/pinduoduo/down.jpg" alt="" srcset="" class="top_down" />
</div>
<input type="text" class="top_input" ref="input" placeholder="苹果14pro百亿补贴" />
<img src="../assets/pinduoduo/carem.jpg" alt="" srcset="" class="top_carem" />
</div>
<span class="top_text">搜索</span>
</div>
<div class="content">
<div class="recently">
<div class="recently_left">
<img src="../assets/pinduoduo/time.jpg" alt="" srcset="" />
<span>最近搜索</span>
</div>
<img src="../assets/pinduoduo/del.jpg" alt="" srcset="" class="del" />
</div>
<div class="recently_content">
<span>啦啦啦啦啦啦啦啦啦啦啦啦</span>
<span>啦啦啦啦啦</span>
<span>啦啦啦啦</span>
</div>
<div class="find">
<div class="find_left">
<img src="../assets/pinduoduo/find.jpg" alt="" srcset="" />
<span>搜索发现</span>
</div>
<img src="../assets/pinduoduo/eye.jpg" alt="" srcset="" class="eye" />
</div>
<div class="recently_content">
<span>iphone14</span>
<span>极光 pro</span>
<span>空调</span>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
interface iStart {
startX: number
x: number
}
const input = ref<HTMLInputElement>()
const searchPage = ref<HTMLDivElement>()
const start: iStart = {
startX: 0,
x: 0
}
const Fnmove = (ev: TouchEvent) => {
start.x = ev.changedTouches[0].pageY - start.startX
if (Math.abs(start.x) >= 1) {
input.value!.blur()
}
document.title = start.x + ''
}
const FnStart = (ev: TouchEvent) => {
start.startX = ev.changedTouches[0].pageY
searchPage.value!.scrollTop = 2
document.ontouchmove = Fnmove
}
onMounted(() => {
console.log(input.value)
searchPage.value!.ontouchstart = FnStart
})
</script>
<style scoped lang="less">
.searchL {
width: 100%;
height: 100vh;
position: fixed;
overflow-y: auto;
background-color: #fff;
}
.search {
width: 100%;
height: calc(100vh + 5px);
background-color: #fff;
}
.top {
display: flex;
justify-content: space-between;
padding: 0 25px;
align-items: center;
box-sizing: border-box;
padding-top: 20px;
.top_left {
width: 18px;
height: 34px;
}
.top_search {
width: 571px;
height: 67px;
background-color: #f2f2f2;
border-radius: 15px;
display: flex;
align-items: center;
position: relative;
.top_shop {
width: 105px;
font-size: 27px;
padding-left: 19px;
box-sizing: border-box;
position: relative;
.top_down {
width: 14px;
height: 8px;
vertical-align: middle;
}
}
.top_shop::after {
content: '';
width: 3px;
height: 29px;
background-color: #d0d0d0;
position: absolute;
right: 0px;
top: 5px;
}
.top_input {
width: 414px;
height: 67px;
outline: none;
background-color: #f2f2f2;
border: 0;
padding-left: 11px;
box-sizing: border-box;
font-size: 27px;
// color: #8b8b8b;
}
.top_carem {
width: 37px;
height: 32px;
position: absolute;
right: 15px;
}
}
.top_text {
font-size: 27px;
color: #e43046;
text-decoration: underline;
}
}
.content {
padding-top: 37px;
box-sizing: border-box;
}
.recently {
display: flex;
justify-content: space-between;
padding: 0 25px;
height: 30px;
.recently_left {
img {
width: 25px;
height: 25px;
margin-bottom: -4px;
}
span {
font-size: 25px;
color: #9d9d9d;
padding-left: 11px;
}
}
.del {
height: 26px;
width: 25px;
vertical-align: middle;
}
}
.recently_content {
display: flex;
padding: 0 25px;
padding-top: 15px;
flex-wrap: wrap;
span {
margin-left: 15px;
margin-top: 15px;
box-sizing: border-box;
padding: 0 18px;
display: inline-block;
max-width: 230px;
height: 56px;
background-color: #f7f7f7;
border-radius: 25px;
font-size: 22px;
text-align: center;
line-height: 56px;
color: #3f3f3f;
// 禁止选择文本
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
// 显示省略号
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.find {
margin-top: 33px;
display: flex;
justify-content: space-between;
padding: 0 25px;
height: 30px;
.find_left {
img {
width: 25px;
height: 25px;
margin-bottom: -4px;
}
span {
font-size: 25px;
color: #9d9d9d;
padding-left: 11px;
}
}
.eye {
width: 29px;
height: 20px;
vertical-align: middle;
}
}
</style>