1. 移动端适配方案
1.1. 视口适配
在Vue项目中设置viewport的最佳实践:
html
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
通过插件自动生成viewport配置:
javascript
// vue.config.js
module.exports = {
chainWebpack: config => {
config.plugin('html').tap(args => {
args[0].meta = {
viewport: 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'
}
return args
})
}
}
1.2. 基于rem/em的适配方案
使用postcss-pxtorem自动转换px为rem:
javascript
// postcss.config.js
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 37.5, // 设计稿宽度的1/10
propList: ['*'],
selectorBlackList: ['.ignore', '.hairlines']
}
}
}
1.3. vw/vh视口单位适配
结合postcss-px-to-viewport实现px自动转换:
javascript
// postcss.config.js
module.exports = {
plugins: {
'postcss-px-to-viewport': {
unitToConvert: 'px',
viewportWidth: 375,
unitPrecision: 5,
propList: ['*'],
viewportUnit: 'vw',
fontViewportUnit: 'vw',
selectorBlackList: [],
minPixelValue: 1,
mediaQuery: false,
replace: true,
exclude: undefined,
include: undefined,
landscape: false,
landscapeUnit: 'vw',
landscapeWidth: 568
}
}
}
1.4. 移动端UI组件库适配
推荐使用适配移动端的Vue组件库:
- Vant (vant-contrib.gitee.io/vant/)
- NutUI (nutui.jd.com/)
- Cube UI (didi.github.io/cube-ui/)
在项目中集成Vant组件库:
bash
npm i vant -S
按需引入组件:
javascript
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import { Button, Cell, CellGroup } from 'vant';
import 'vant/lib/index.css';
const app = createApp(App);
app.use(Button)
.use(Cell)
.use(CellGroup);
app.mount('#app')
2. 移动端性能优化技巧
2.1. 虚拟列表实现长列表优化
可以使用vue-virtual-scroller实现高性能列表:
bash
npm install vue-virtual-scroller --save
javascript
<template>
<RecycleScroller
class="items-container"
:items="items"
:item-size="32"
key-field="id"
>
<template #item="{ item }">
<div class="item">{{ item.text }}</div>
</template>
</RecycleScroller>
</template>
<script>
import { RecycleScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
export default {
components: {
RecycleScroller
},
data() {
return {
items: Array.from({ length: 10000 }).map((_, i) => ({
id: i,
text: `Item ${i}`
}))
}
}
}
</script>
2.2. 图片懒加载与优化
使用vueuse的useIntersectionObserver实现图片懒加载:
bash
npm i @vueuse/core
javascript
<template>
<img
v-for="item in imageList"
:key="item.id"
:src="item.loaded ? item.src : placeholder"
@load="handleImageLoad(item)"
class="lazy-image"
>
</template>
<script>
import { ref, onMounted } from 'vue'
import { useIntersectionObserver } from '@vueuse/core'
export default {
setup() {
const imageList = ref([
{ id: 1, src: 'https://example.com/image1.jpg', loaded: false },
{ id: 2, src: 'https://example.com/image2.jpg', loaded: false },
// 更多图片...
])
const placeholder = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='
const handleImageLoad = (item) => {
item.loaded = true
}
onMounted(() => {
imageList.value.forEach(item => {
const el = ref(null)
const { stop } = useIntersectionObserver(
el,
([{ isIntersecting }]) => {
if (isIntersecting) {
item.loaded = true
stop()
}
}
)
})
})
return {
imageList,
placeholder,
handleImageLoad
}
}
}
</script>
2.3. 减少首屏加载时间
使用Vue的异步组件和路由懒加载:
javascript
// 路由配置
const routes = [
{
path: '/home',
name: 'Home',
component: () => import(/* webpackChunkName: "home" */ '../views/Home.vue')
},
{
path: '/about',
name: 'About',
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
使用CDN加载外部资源:
html
<!-- index.html -->
<head>
<!-- 加载Vue -->
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
2.4. 事件节流与防抖
使用lodash的throttle和debounce函数:
bash
npm install lodash --save
vue
<template>
<div>
<input v-model="searchText" @input="debouncedSearch" placeholder="搜索...">
</div>
</template>
<script>
import { debounce } from 'lodash'
export default {
data() {
return {
searchText: '',
debouncedSearch: null
}
},
created() {
this.debouncedSearch = debounce(this.handleSearch, 300)
},
methods: {
handleSearch() {
// 执行搜索操作
console.log('Searching with:', this.searchText)
}
}
}
</script>
3. 移动端常见问题解决方案
3.1. 移动端300ms点击延迟问题
使用fastclick库解决:
bash
npm install fastclick --save
javascript
// main.js
import FastClick from 'fastclick'
FastClick.attach(document.body)
3.2. 滚动卡顿问题
优化滚动性能:
css
.scroll-container {
-webkit-overflow-scrolling: touch; /* 开启硬件加速 */
overflow-y: auto;
}
3.3. 移动端适配iOS安全区域
css
/* 适配iOS安全区域 */
body {
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);
}
3.4. 解决1px边框问题
css
/* 0.5px边框 */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
.border-bottom {
border-bottom: 0.5px solid #e5e5e5;
}
}
4. 性能监控与分析
使用Lighthouse进行性能评估:
bash
npm install -g lighthouse
lighthouse https://your-vue-app.com --view
使用Vue DevTools进行性能分析:
- 在Chrome浏览器中安装Vue DevTools扩展
- 在Vue项目中启用性能模式:
javascript
// main.js
const app = createApp(App)
if (process.env.NODE_ENV !== 'production') {
app.config.performance = true
}
app.mount('#app')
5. 实战案例:开发响应式移动端应用
5.1. 项目初始化
bash
npm init vite@latest my-mobile-app -- --template vue-ts
cd my-mobile-app
npm install
5.2. 配置适配方案
集成postcss-px-to-viewport:
bash
npm install postcss-px-to-viewport --save-dev
配置postcss.config.js:
javascript
module.exports = {
plugins: {
'postcss-px-to-viewport': {
unitToConvert: 'px',
viewportWidth: 375,
unitPrecision: 5,
propList: ['*'],
viewportUnit: 'vw',
fontViewportUnit: 'vw',
selectorBlackList: [],
minPixelValue: 1,
mediaQuery: false,
replace: true,
exclude: /node_modules/i
}
}
}
5.3. 集成Vant组件库
bash
npm install vant --save
配置按需引入:
javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
import { VantResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [VantResolver()],
}),
],
})
5.4. 实现响应式布局
vue
<template>
<div class="container">
<van-nav-bar title="我的应用" left-arrow @click-left="onClickLeft" />
<van-swipe class="banner" :autoplay="3000" indicator-color="white">
<van-swipe-item v-for="(item, index) in banners" :key="index">
<img :src="item" alt="Banner" />
</van-swipe-item>
</van-swipe>
<van-grid :columns-num="4">
<van-grid-item v-for="(item, index) in gridItems" :key="index" :text="item.text" :icon="item.icon" />
</van-grid>
<van-list
v-model:loading="loading"
:finished="finished"
finished-text="没有更多了"
@load="onLoad"
>
<van-cell v-for="(item, index) in list" :key="index" :title="item.title" :value="item.value" is-link />
</van-list>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, onMounted } from 'vue'
export default defineComponent({
setup() {
const banners = ref([
'https://picsum.photos/600/200?random=1',
'https://picsum.photos/600/200?random=2',
'https://picsum.photos/600/200?random=3'
])
const gridItems = ref([
{ icon: 'photo-o', text: '图片' },
{ icon: 'video-o', text: '视频' },
{ icon: 'music-o', text: '音乐' },
{ icon: 'friends-o', text: '社交' }
])
const list = ref([])
const loading = ref(false)
const finished = ref(false)
const onLoad = () => {
// 模拟加载数据
setTimeout(() => {
for (let i = 0; i < 10; i++) {
list.value.push({
title: `标题 ${list.value.length + 1}`,
value: '内容'
})
}
// 加载状态结束
loading.value = false
// 数据全部加载完成
if (list.value.length >= 50) {
finished.value = true
}
}, 1000)
}
onMounted(() => {
onLoad()
})
const onClickLeft = () => {
console.log('返回')
}
return {
banners,
gridItems,
list,
loading,
finished,
onLoad,
onClickLeft
}
}
})
</script>
<style scoped>
.banner img {
width: 100%;
height: 180px;
object-fit: cover;
}
</style>
通过以上步骤,我们可以开发出一个适配移动端的Vue应用。
本次分享就到这儿啦,我是鹏多多,如果看了觉得有帮助的,欢迎 点赞 关注 评论,在此谢过道友;
往期文章
- vue计算属性computed的详解
- Web图像编辑神器tui.image-editor从基础到进阶的实战指南
- 开发个人微信小程序类目选择/盈利方式/成本控制与服务器接入指南
- flutter-使用confetti制作炫酷纸屑爆炸粒子动画
- 前端图片裁剪Cropper.js核心功能与实战技巧详解
- 编辑器也有邪修?盘点VS Code邪门/有趣的扩展
- flutter-使用AnimatedDefaultTextStyle实现文本动画
- js使用IntersectionObserver实现目标元素可见度的交互
- Web前端页面开发阿拉伯语种适配指南
- 让网页拥有App体验?PWA 将网页变为桌面应用的保姆级教程PWA
- 助你上手Vue3全家桶之Vue3教程
- 使用nvm管理node.js版本以及更换npm淘宝镜像源
- 超详细!Vue的十种通信方式
- 手把手教你搭建规范的团队vue项目,包含commitlint,eslint,prettier,husky,commitizen等等