文章目录
- 1. 移动端适配方案
- 1.1. 视口适配
- 1.2. 基于rem/em的适配方案
- 1.3. vw/vh视口单位适配
- 1.4. 移动端UI组件库适配
- 2. 移动端性能优化技巧
- 2.1. 虚拟列表实现长列表优化
- 2.2. 图片懒加载与优化
- 2.3. 减少首屏加载时间
- 2.4. 事件节流与防抖
- 3. 移动端常见问题解决方案
- 3.1. 移动端300ms点击延迟问题
- 3.2. 滚动卡顿问题
- 3.3. 移动端适配iOS安全区域
- 3.4. 解决1px边框问题
- 4. 性能监控与分析
- 5. 实战案例:开发响应式移动端应用
- 5.1. 项目初始化
- 5.2. 配置适配方案
- 5.3. 集成Vant组件库
- 5.4. 实现响应式布局
1. 移动端适配方案
1.1. 视口适配
在Vue项目中设置viewport的最佳实践:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
通过插件自动生成viewport配置:
// 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:
// postcss.config.js
module.exports = {plugins: {'postcss-pxtorem': {rootValue: 37.5, // 设计稿宽度的1/10propList: ['*'],selectorBlackList: ['.ignore', '.hairlines']}}
}
1.3. vw/vh视口单位适配
结合postcss-px-to-viewport实现px自动转换:
// 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 (https://vant-contrib.gitee.io/vant/)
- NutUI (https://nutui.jd.com/)
- Cube UI (https://didi.github.io/cube-ui/)
在项目中集成Vant组件库:
npm i vant -S
按需引入组件:
// 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实现高性能列表:
npm install vue-virtual-scroller --save
<template><RecycleScrollerclass="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实现图片懒加载:
npm i @vueuse/core
<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 = truestop()}})})})return {imageList,placeholder,handleImageLoad}}
}
</script>
2.3. 减少首屏加载时间
使用Vue的异步组件和路由懒加载:
// 路由配置
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加载外部资源:
<!-- 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函数:
npm install lodash --save
<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库解决:
npm install fastclick --save
// main.js
import FastClick from 'fastclick'FastClick.attach(document.body)
3.2. 滚动卡顿问题
优化滚动性能:
.scroll-container {-webkit-overflow-scrolling: touch; /* 开启硬件加速 */overflow-y: auto;
}
3.3. 移动端适配iOS安全区域
/* 适配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边框问题
/* 0.5px边框 */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {.border-bottom {border-bottom: 0.5px solid #e5e5e5;}
}
4. 性能监控与分析
使用Lighthouse进行性能评估:
npm install -g lighthouse
lighthouse https://your-vue-app.com --view
使用Vue DevTools进行性能分析:
- 在Chrome浏览器中安装Vue DevTools扩展
- 在Vue项目中启用性能模式:
// main.js
const app = createApp(App)if (process.env.NODE_ENV !== 'production') {app.config.performance = true
}app.mount('#app')
5. 实战案例:开发响应式移动端应用
5.1. 项目初始化
npm init vite@latest my-mobile-app -- --template vue-ts
cd my-mobile-app
npm install
5.2. 配置适配方案
集成postcss-px-to-viewport:
npm install postcss-px-to-viewport --save-dev
配置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: /node_modules/i}}
}
5.3. 集成Vant组件库
npm install vant --save
配置按需引入:
// 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. 实现响应式布局
<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-listv-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中ref的详解以及react的ref对比
- css使用aspect-ratio制作4:3和9:16和1:1等等比例布局
- Web前端页面开发阿拉伯语种适配指南
- flutter-使用extended_image操作图片的加载和状态处理以及缓存和下载
- flutter-制作可缩放底部弹出抽屉评论区效果
- flutter-实现Tabs吸顶的PageView效果
- Vue2全家桶+Element搭建的PC端在线音乐网站
- 助你上手Vue3全家桶之Vue3教程
- 超详细!vue组件通信的10种方式
- 超详细!Vuex手把手教程
- 使用nvm管理node.js版本以及更换npm淘宝镜像源
- vue中利用.env文件存储全局环境变量,以及配置vue启动和打包命令
个人主页
- CSDN
- GitHub
- 掘金