手拉手带你用 Vue3 + VantUI 写一个移动端脚手架 系列二 (页面布局与兼容)

简介: 用 Vue3 + VantUI 写一个移动端脚手架

261890fed8013949a9dbc23f1b41188.png

项目地址(持续迭代中):github.com/jyliyue/vit…

系列文章:

前言

上一篇已经就项目结构和常用插件的配置给大家做了简单的介绍,本篇主要会从移动端页面布局常见兼容问题展开做讲解,废话不多,马上开始!

页面容器组件

思路

移动端页面一般采用最外层容器固定宽高,内部使用 弹性布局flex 处理,移动端的样式布局建议大家能使用 flex 弹性就使用 flex ,尽量少使用 calc(XX) 计算属性,一方面使用 calc 会有一定的 性能损耗,另一方面看过很多案例使用 calc 通常是配合 100vh 计算页面某一区域的高度,这两者加起来很多时候就会让页面在不同的屏幕下表现不一致,所以为了降低日后的维护负担,还是尽量强迫自己学着用 flex 花式解决布局问题 ^_^

为了保持所有页面布局的一致性,也为了日后维护时能统一处理一些兼容性问题,该项目统一封装 组件作为页面容器

关于 100 vh 与 html, body { height: 100% }

首先,这两种方法大家应该都很熟悉,都可以让我们获取一个全屏元素,大家在写代码时也时不时会用到,但是在一些场景下却会产生一些不可预料的问题,所以在选择方案上很重要,这是移动端布局的基础,打好地基很重要,这里我们先看下淘宝的做法

01a487f8c12c57a619efdee60407163.png

这里大家应该就有疑问了,为什么不使用 100vh 而是使用 html, body { height: 100% }

  • 首先我们来了解下 100vh
    1vh单位代表了屏幕可视区域的1% ,vh 获取的是视窗高度,100vh 在开发中浏览器预览时页面占据整个可视区域没有任何问题
    但是,核心问题是移动浏览器(Chrome和Safari)有一个 “ 特性 ” ,地址栏有时可见,有时隐藏,改变了视口的可见大小。这些浏览器没有将100vh的高度调整为视口高度变化时屏幕的可见部分,而是将100vh设置为隐藏地址栏的浏览器高度。结果是,当地址栏可见时,屏幕的底部部分将被切断,从而破坏了100vh的初衷

61ab407d5e13754fe54471e4ae86987.png

  • html, body { height: 100% }
    首先 html 设置 height: 100% 表示可视区域窗口的大小,而 html 的高度会随着窗口可用区的高度增大而增大,减小而减小,这样我们就不用怕地址栏影响可视区域了
    然后需要注意用 body 继承下 html 的高度属性就可以生效了,一般项目中这样配置就可以
html,
body,
#app {
    width: 100%;
    height: 100%;
}
复制代码

页面组件结构设计

274fa556c5b36e7bd49d072ebcd913e.png

组件实现

<template>
    <div class="app-page">
        <div class="app-main">
            <slot></slot>
        </div>
    </div>
</template>
<style lang="scss" scoped>
.app-page {
    position: relative;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    .app-main {
        flex: 1;
        overflow: auto;
    }
}
</style>
复制代码

标题栏实现

标题栏我们希望它能根据我们路由里定义的标题动态显示页面标题,其次支持可以动态的控制标题栏的显示与隐藏,毕竟有的时我们的页面是不需要显示标题栏的,因为我们项目使用的是 ui 框架是 vant-ui,这里就直接拿 进行改造

<script setup>
// This starter template is using Vue 3 <script setup> SFCs
defineProps({
    navBar: {
        type: Boolean,
        default: true
    },
    leftArrow: {
        type: Boolean,
        default: true
    },
    onClickLeft: {
        type: Function,
        default: () => history.back()
    }
})
const route = useRoute()
</script>
<template>
    <div class="app-page">
        <van-nav-bar
            v-if="navBar"
            :title="route.meta.title"
            :left-arrow="leftArrow"
            @click-left="onClickLeft"
        />
        <div class="app-main">
            <slot></slot>
        </div>
    </div>
</template>
复制代码

这样就完工了,后续所有的页面都用 组件作为根组件包裹,来保障所有页面结构统一,后续有兼容调整的话,也只要在组件中处理就好了

页面应用

<template>
    <app-page>
        <div> ... 开始开发 ... </div>
    </app-page>
</template>
复制代码

移动端兼容

ios 网页消除阻尼回弹效果

通过固定应用内容区域,消除最外层的拖拽界面抖动,让我们整个应用的功能都在 #app 这个固定宽高的盒子内完成,然后关键点是让 #app 容器隐藏溢出元素 overflow: hidden

html,
body,
#app {
    width: 100%;
    height: 100%;
    // 解决 ios 界面回弹
    overflow: hidden;
}
复制代码

ios 底部安全区域样式处理

使用 ios 提供的 safe-area-inset-topsafe-area-inset-bottom 做上下安全区域的兼容处理

#app {
    // 顶部安全区
    padding-top: constant(safe-area-inset-top);
    padding-top: env(safe-area-inset-top);
    // 底部安全区
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
}
复制代码

需要注意H5网页 meta 要设置 viewport-fit=cover 的时候才会生效

移动端 click 延时问题

移动端之所以会有点击 300ms 的延时,原因是移动端屏幕双击会缩放,需要一个判定时间,所以解决这个问题简单粗暴点只要禁用掉屏幕的缩放功能就好了

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, viewport-fit=cover">
复制代码

此外,也可以借助 fastclick 插件解决300ms延迟

ios 时间格式的坑

这个算是顺便给大家提个醒,在做移动端项目时不要使用 new Date().getTime() 去处理 2022-10-14 之类格式的时间为时间戳,特别是用到 datePicker 之类的组件时要格外注意,例如

new Date("2022-01-17 10:00").getTime() // NaN
复制代码

这样你在 ios 下会获得一个 NaN 的异常返回,原因是 ios 下对数字中间的横杆 - 转化会有问题,需要转化为斜杆处理 /

const timestamp = (new Date('2021-07-28 18:00'.replace(/-/g, '/'))).getTime()
复制代码

目前本项目对移动端的兼容处理还比较简单,主要是针对 ios 端一些常见问题的处理,后续想到什么会不断完善补充,仓库也会定期更新,大家多多关注

项目地址(持续迭代中):github.com/jyliyue/vit…

好了,本篇对移动端项目的页面容器介绍和一些常见兼容问题的科普告一段落,下篇开始会对该项目的状态缓存管理体系 pinia 和 vue3 中 keep-alive 的应用做介绍,并带大家一起封装一个移动端常用的列表组件,支持接口配置化以及进入详情返回列表时记录位置等常用功能,敬请大家期待!

相关文章
|
13天前
|
缓存 JavaScript UED
Vue3中v-model在处理自定义组件双向数据绑定时有哪些注意事项?
在使用`v-model`处理自定义组件双向数据绑定时,要仔细考虑各种因素,确保数据的准确传递和更新,同时提供良好的用户体验和代码可维护性。通过合理的设计和注意事项的遵循,能够更好地发挥`v-model`的优势,实现高效的双向数据绑定效果。
117 64
|
13天前
|
JavaScript 前端开发 API
Vue 3 中 v-model 与 Vue 2 中 v-model 的区别是什么?
总的来说,Vue 3 中的 `v-model` 在灵活性、与组合式 API 的结合、对自定义组件的支持等方面都有了明显的提升和改进,使其更适应现代前端开发的需求和趋势。但需要注意的是,在迁移过程中可能需要对一些代码进行调整和适配。
|
1月前
|
JavaScript 前端开发 开发者
Vue 3中的Proxy
【10月更文挑战第23天】Vue 3中的`Proxy`为响应式系统带来了更强大、更灵活的功能,解决了Vue 2中响应式系统的一些局限性,同时在性能方面也有一定的提升,为开发者提供了更好的开发体验和性能保障。
64 7
|
1月前
|
JavaScript 数据管理 Java
在 Vue 3 中使用 Proxy 实现数据双向绑定的性能如何?
【10月更文挑战第23天】Vue 3中使用Proxy实现数据双向绑定在多个方面都带来了性能的提升,从更高效的响应式追踪、更好的初始化性能、对数组操作的优化到更优的内存管理等,使得Vue 3在处理复杂的应用场景和大量数据时能够更加高效和稳定地运行。
52 1
|
1月前
|
JavaScript 开发者
在 Vue 3 中使用 Proxy 实现数据的双向绑定
【10月更文挑战第23天】Vue 3利用 `Proxy` 实现了数据的双向绑定,无论是使用内置的指令如 `v-model`,还是通过自定义事件或自定义指令,都能够方便地实现数据与视图之间的双向交互,满足不同场景下的开发需求。
56 1
|
20天前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
34 1
vue学习第四章
|
20天前
|
JavaScript 前端开发
vue学习第九章(v-model)
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript与Vue的大一学生,自学前端2年半,正向全栈进发。此篇介绍v-model在不同表单元素中的应用及修饰符的使用,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
28 1
vue学习第九章(v-model)
|
20天前
|
JavaScript 前端开发 开发者
vue学习第十章(组件开发)
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文深入讲解Vue组件的基本使用、全局与局部组件、父子组件通信及数据传递等内容,适合前端开发者学习参考。持续更新中,期待您的关注!🎉🎉🎉
33 1
vue学习第十章(组件开发)
|
25天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
26天前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。