学习 uni-app 专业课的这段时间里,我从对跨平台开发一无所知,到能够独立完成一些简单的应用项目,收获颇丰。这门课程不仅让我掌握了实用的开发技能,更培养了我解决问题的思维方式。下面,我将结合学习过程中的实际经历和代码案例,分享我的学习心得。
目录
一、初识 uni-app:打破平台壁垒的神奇工具
刚开始接触 uni-app 时,老师告诉我们,它是一个可以实现 “一次开发,多端部署” 的框架,能够让我们用一套代码同时开发出适配微信小程序、H5、APP 等多个平台的应用。这对于我这种刚接触开发的新手来说,既新奇又充满挑战。
在安装好开发环境,打开第一个 uni-app 项目模板时,我看到了简洁的项目结构。pages文件夹存放页面文件,static文件夹用于放置静态资源,main.js是项目的入口文件。通过阅读官方文档和老师的讲解,我了解到 uni-app 使用的是 Vue.js 语法,这让有一点 HTML、CSS 和 JavaScript 基础的我,学习起来轻松了许多。
比如,在一个简单的 Hello World 页面中,代码如下:
<template>
<view class="content">
<text class="title">{{ message }}</text>
</view>
</template>
<script>
export default {
data() {
return {
message: 'Hello, uni-app!'
}
}
}
</script>
<style>
.content {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.title {
font-size: 36rpx;
color: #333;
}
</style>
在这段代码中,<template>标签定义了页面的结构,使用类似于 HTML 的语法,不过这里用的是<view>代替<div>作为容器。<script>部分是 Vue.js 的逻辑代码,通过data属性定义了一个message变量,在页面中通过双花括号{{}}进行数据绑定。<style>则是用于编写样式,这里使用了 rpx 作为单位,它可以根据不同设备的屏幕尺寸自动进行适配,这是 uni-app 在移动端开发中的一个贴心设计。
二、学习进阶:页面交互与组件化开发
随着学习的深入,我们开始接触页面交互和组件化开发。页面交互中,最常用的就是事件绑定。例如,在一个按钮点击事件中:
<template>
<view class="button-container">
<button @click="handleClick">点击我</button>
<text v-if="showMessage">按钮被点击了!</text>
</view>
</template>
<script>
export default {
data() {
return {
showMessage: false
}
},
methods: {
handleClick() {
this.showMessage = true;
}
}
}
</script>
<style>
.button-container {
display: flex;
flex-direction: column;
align-items: center;
}
</style>
在上述代码里,@click是 uni-app 中绑定点击事件的方式,它绑定了handleClick方法。当按钮被点击时,handleClick方法会将showMessage变量设置为true,通过v-if指令,控制<text>标签的显示与隐藏,从而实现点击按钮后显示提示信息的效果。
组件化开发则是提高开发效率和代码复用性的关键。我们可以将一些常用的功能封装成组件,在多个页面中使用。比如,我封装了一个简单的搜索框组件:
<!-- search-box.vue -->
<template>
<view class="search-box">
<input type="text" v-model="searchText" placeholder="请输入搜索内容" />
<button @click="search">搜索</button>
</view>
</template>
<script>
export default {
data() {
return {
searchText: ''
}
},
methods: {
search() {
// 这里可以添加实际的搜索逻辑,比如调用接口
console.log('搜索内容:', this.searchText);
}
}
}
</script>
<style>
.search-box {
display: flex;
align-items: center;
border: 1px solid #ccc;
border-radius: 5px;
padding: 5px;
}
input {
flex: 1;
border: none;
outline: none;
}
button {
margin-left: 5px;
}
</style>
使用这个组件时,在页面的template中引入:
<template>
<view>
<search-box></search-box>
</view>
</template>
<script>
import searchBox from '@/components/search-box.vue';
export default {
components: {
searchBox
}
}
</script>
通过这种方式,将搜索框的功能封装成组件,在其他需要搜索功能的页面,直接引入使用,大大减少了重复代码的编写,也方便后期维护和修改。
三、实战项目:遇到的问题与解决方法
在课程的实战项目中,我参与开发一个校园二手交易小程序。在这个过程中,遇到了不少问题。
其中一个问题是页面数据加载缓慢。通过排查,发现是接口请求过于频繁,而且没有做数据缓存。后来,我们使用了 uni-app 提供的uni.setStorageSync和uni.getStorageSync方法来实现简单的数据缓存。例如,在获取商品列表时:
// 获取商品列表
async function getGoodsList() {
const cachedData = uni.getStorageSync('goodsList');
if (cachedData) {
return cachedData;
}
const res = await uni.request({
url: 'https://example.com/api/goodsList',
method: 'GET'
});
if (res.statusCode === 200) {
uni.setStorageSync('goodsList', res.data);
return res.data;
}
return [];
}
上述代码先尝试从缓存中获取数据,如果有缓存数据则直接返回,没有则发起接口请求,请求成功后将数据存入缓存,下次再获取时就可以直接从缓存读取,提高了数据加载速度。
另一个问题是页面跳转时的传参问题。在商品详情页需要展示商品的详细信息,这些信息需要从列表页传递过来。我们使用了uni.navigateTo的url参数传递数据,例如:
// 列表页点击商品跳转到详情页
handleGoodsClick(goods) {
uni.navigateTo({
url: `/pages/goodsDetail/goodsDetail?id=${goods.id}&name=${goods.name}&price=${goods.price}`
});
}
在商品详情页,通过onLoad生命周期函数获取传递过来的参数:
export default {
data() {
return {
goods: {}
}
},
onLoad(options) {
this.goods.id = options.id;
this.goods.name = options.name;
this.goods.price = options.price;
}
}
通过这种方式,实现了页面之间的数据传递,保证了商品详情页能够正确展示对应的商品信息。
在校园二手交易小程序开发中,除了数据加载和页面传参问题,我们还遭遇了许多 “拦路虎”,这些经历让我对 uni-app 的应用有了更深刻的理解。
1. 复杂页面布局适配难题
当设计商品展示列表时,我们希望实现多列卡片式布局,并且在不同屏幕尺寸下都能保持美观和可读性。起初,使用常规的 flex 布局在部分手机上出现了元素错位、图片变形的情况。通过查阅资料,我发现 uni-app 支持@media媒体查询,结合rpx单位能更好地实现响应式布局。
例如,我们将商品卡片设置为两列布局,代码如下:
.goods-list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.goods-card {
width: 49%;
margin-bottom: 15rpx;
border: 1px solid #ccc;
border-radius: 10rpx;
padding: 15rpx;
}
@media (max-width: 375px) {
.goods-card {
width: 100%;
}
}
在上述代码中,正常情况下商品卡片宽度占比 49%,实现两列排列;当屏幕宽度小于等于 375px(类似 iPhone SE 等小屏设备)时,通过媒体查询将卡片宽度调整为 100%,变为单列布局,有效解决了小屏设备上的显示问题 。
2. 表单验证与用户体验优化
在发布商品页面,我们需要对用户输入的商品信息进行严格验证,如标题长度限制、价格必须为数字等。最初直接在提交按钮的点击事件中进行验证,这样不仅代码冗余,而且用户体验不佳 —— 一旦输入有误就直接阻止提交,没有明确提示。
后来,我们采用了自定义指令结合正则表达式的方式进行优化。先创建一个自定义指令v-validate:
// main.js中注册自定义指令
Vue.directive('validate', {
inserted: function (el, binding) {
el.addEventListener('blur', function () {
const value = el.value;
const { pattern, message } = binding.value;
const reg = new RegExp(pattern);
if (!reg.test(value)) {
uni.showToast({
title: message,
icon: 'none'
});
el.value = '';
}
});
}
});
在表单输入框中使用该指令:
<template>
<view class="publish-form">
<input v-model="goods.title" v-validate="{pattern: '^.{2,20}$', message: '标题需2-20字'}" placeholder="请输入商品标题" />
<input v-model.number="goods.price" v-validate="{pattern: '^[0-9]+(.[0-9]{1,2})?$', message: '价格需为有效数字'}" placeholder="请输入商品价格" />
<button @click="submitForm">发布商品</button>
</view>
</template>
这样,当用户输入内容失去焦点时,就会触发验证,如果不符合规则,会弹出提示框并清空输入内容,既保证了数据准确性,又提升了用户体验。
3. 与后端联调的接口适配问题
在与后端进行数据交互时,接口返回的数据格式与前端预期不一致,导致页面渲染出错。例如,后端返回的时间字段是时间戳,而前端需要展示为 “YYYY-MM-DD HH:mm:ss” 的格式。我们通过在main.js中设置全局过滤器来解决这个问题:
// main.js中设置全局过滤器
Vue.filter('formatDate', function (value) {
if (!value) return '';
const date = new Date(value);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hour = String(date.getHours()).padStart(2, '0');
const minute = String(date.getMinutes()).padStart(2, '0');
const second = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
});
在页面中使用过滤器:
<template>
<view class="goods-item">
<text>发布时间:{{ goods.createTime | formatDate }}</text>
</view>
</template>
通过这种方式,将时间戳统一转换为指定格式,确保了数据展示的一致性。
四、学习总结与未来展望
经过这次实战项目的打磨,我深刻体会到 uni-app 开发不仅仅是代码的堆砌,更是对细节把控、问题解决能力的全面考验。在日常学习中,我们容易停留在基础语法和简单功能的实现上,而实战则暴露了许多知识盲区,促使我不断查阅资料、向老师和同学请教,逐步构建起完整的开发思维。
未来,我计划深入研究 uni-app 的插件市场,探索如何引入第三方插件来拓展应用功能,如集成支付功能、地图导航等。同时,我也希望学习 uni-app 的性能优化技巧,比如首屏加载优化、内存管理等,让开发出的应用更加流畅高效。此外,我还想尝试将 uni-app 与不同的后端框架结合,如 Node.js、Spring Boot,进一步提升全栈开发能力。
学习 uni-app 的道路永无止境,我会将每一次遇到的问题都当作成长的契机,持续深耕跨平台开发领域,争取在未来能够开发出更具创新性和实用性的应用作品。
希望我的这些学习心得和实战经验,能够为正在学习 uni-app 的小伙伴们提供一些帮助。如果你在开发过程中也遇到了有趣的问题或有更好的解决方案,欢迎在评论区交流分享,让我们一起在技术学习的道路上共同进步!