发布日期:2024年2月25日
一、项目架构设计
本教程将开发一个完整的智能家居控制应用,支持以下功能:
- 多端适配:iOS/Android/小程序/H5
- 设备管理:蓝牙/WiFi设备连接
- 实时控制:WebSocket即时通信
- 场景联动:自动化规则引擎
- 数据可视化:Echarts图表集成
技术栈:UniApp + Vue3 + uView UI + MQTT + ECharts
二、环境准备与项目初始化
1. 创建UniApp项目
# 使用Vue3/Vite模板
npx degit dcloudio/uni-preset-vue#vite my-smart-home
# 安装依赖
cd my-smart-home
npm install
npm install uview-ui mqtt echarts
2. 目录结构规划
src/
├── api/ # 接口服务
├── components/ # 公共组件
├── composables/ # Vue组合式API
├── pages/ # 页面组件
├── static/ # 静态资源
├── store/ # Pinia状态管理
├── styles/ # 全局样式
├── utils/ # 工具函数
├── App.vue # 应用入口
└── main.js # 主配置文件
三、核心功能实现
1. 多端设备连接
// utils/device-connector.js
export function connectBluetoothDevice() {
return new Promise((resolve, reject) => {
uni.openBluetoothAdapter({
success: (res) => {
uni.startBluetoothDevicesDiscovery({
services: ['0000FFE0-0000-1000-8000-00805F9B34FB'],
success: (discoveryRes) => {
uni.onBluetoothDeviceFound((foundRes) => {
const device = foundRes.devices.find(d =>
d.name.startsWith('SMART_'));
if (device) {
uni.stopBluetoothDevicesDiscovery();
resolve(device);
}
});
}
});
},
fail: reject
});
});
}
// WiFi设备连接
export function connectWifiDevice(ssid, password) {
return uni.connectWifi({
SSID: ssid,
password: password,
BSSID: ''
});
}
2. MQTT实时通信
// composables/useMqtt.js
import mqtt from 'mqtt/dist/mqtt.min';
export function useMqtt() {
const client = ref(null);
const messages = ref([]);
const connect = (options) => {
client.value = mqtt.connect('wxs://iot.example.com/mqtt', {
clientId: `client_${Date.now()}`,
username: 'smart_home',
password: 'secure_password',
...options
});
client.value.on('connect', () => {
uni.showToast({ title: '设备已连接', icon: 'success' });
});
client.value.on('message', (topic, payload) => {
messages.value.push({
topic,
payload: JSON.parse(payload.toString())
});
});
};
const subscribe = (topic) => {
client.value?.subscribe(topic, { qos: 1 });
};
const publish = (topic, message) => {
client.value?.publish(topic, JSON.stringify(message));
};
return { client, messages, connect, subscribe, publish };
}
四、UI组件开发
1. 设备控制卡片
<template>
<view class="device-card" :class="{ 'active': device.status }">
<u-icon :name="device.icon" size="28"></u-icon>
<text class="name">{{ device.name }}</text>
<u-switch
v-model="device.status"
@change="handleDeviceToggle"
active-color="#07c160"
></u-switch>
</view>
</template>
<script setup>
const props = defineProps({
device: {
type: Object,
required: true
}
});
const handleDeviceToggle = (value) => {
uni.showLoading({ title: '控制中...' });
publish(`device/${props.device.id}/control`, {
command: value ? 'ON' : 'OFF'
});
};
</script>
2. 场景自动化编辑器
<template>
<view class="scene-editor">
<draggable
v-model="triggers"
group="triggers"
handle=".drag-handle"
>
<view
v-for="(trigger, index) in triggers"
:key="index"
class="trigger-item"
>
<u-icon name="list-dot" class="drag-handle"></u-icon>
<trigger-config :model="trigger" />
<u-icon
name="trash"
@click="removeTrigger(index)"
></u-icon>
</view>
</draggable>
<u-button @click="addTrigger">添加触发条件</u-button>
</view>
</template>
五、多端适配方案
1. 条件编译处理
// 平台特定代码处理
function shareDevice(device) {
// #ifdef MP-WEIXIN
wx.shareAppMessage({
title: `分享${device.name}控制权限`,
path: `/pages/device/share?id=${device.id}`
});
// #endif
// #ifdef APP-PLUS
plus.share.sendWithSystem({
type: 'text',
content: `设备分享:${device.name}`
});
// #endif
// #ifdef H5
navigator.clipboard.writeText(
`${location.origin}/#/pages/device/share?id=${device.id}`
);
uni.showToast({ title: '链接已复制' });
// #endif
}
2. 响应式布局设计
<template>
<view class="dashboard">
<view class="grid" :style="gridStyle">
<device-card
v-for="device in devices"
:key="device.id"
:device="device"
/>
</view>
</view>
</template>
<script setup>
import { computed } from 'vue';
import { useWindowSize } from '@vueuse/core';
const { width } = useWindowSize();
const gridStyle = computed(() => {
const columnWidth = width.value > 768 ? 200 : 150;
const columns = Math.floor(width.value / columnWidth);
return {
'grid-template-columns': `repeat(${columns}, 1fr)`
};
});
</script>
六、性能优化实践
1. 图片懒加载
<template>
<image
:src="placeholder"
:lazy-load="true"
:data-src="realSrc"
@load="handleImageLoad"
@error="handleImageError"
/>
</template>
<script setup>
const props = defineProps({
src: String
});
const realSrc = ref('');
const placeholder = '/static/placeholder.png';
const handleImageLoad = (e) => {
const observer = uni.createIntersectionObserver(this);
observer.relativeToViewport();
observer.observe('.lazy-image', (res) => {
if (res.intersectionRatio > 0) {
realSrc.value = props.src;
observer.disconnect();
}
});
};
</script>
2. 数据缓存策略
// utils/cache.js
export function createCacheWrapper(fn, key, ttl = 300) {
return async (...args) => {
try {
const cached = uni.getStorageSync(key);
if (cached && Date.now() - cached.timestamp {
const res = await uni.request({ url: '/api/devices' });
return res.data;
}, 'device_list', 600);
七、打包发布流程
1. 多平台构建命令
# 微信小程序
npm run build:mp-weixin
# H5
npm run build:h5
# Android App
npm run build:app-plus &&
cd dist/build/app-plus &&
zip -r ../android.zip ./*
# iOS App (需Xcode)
npm run build:app-plus &&
open /dist/build/app-plus/ios
2. 自动化部署配置
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install dependencies
run: npm install
- name: Build for WeChat
run: npm run build:mp-weixin
- name: Deploy to CDN
uses: actions/upload-artifact@v2
with:
name: weapp-build
path: dist/build/mp-weixin
八、总结与扩展
通过本教程,您已经掌握了:
- UniApp跨平台开发全流程
- 物联网设备连接与控制
- 实时通信与状态管理
- 多端适配与性能优化
扩展学习方向:
- UniApp插件开发
- 原生能力扩展(Android/iOS)
- WebAssembly性能优化
- 小程序云开发集成