第1章 1.1 uniapp 介绍与跨端原理

Simple tech illustration explaining a key concept about "第1章 1.1 uniapp 介绍与跨端原理", infographic style

AI comic creation scene, creative workspace with holographic UI panels, soft futuristic aesthetic, n

🎯 开场:做一个 App 到底有多难?

你有没有过这种经历——

想做一个「校园二手交易」的小 App,给同学用。结果你发现:

  • 做 iOS 版要找 Mac,要学 Swift
  • 做安卓版要找 Windows,要学 Java/Kotlin
  • 做小程序版又要学 WXML/WXSS
  • 老板说「再加个 Web 端吧」……

一个需求,三套代码,三套bug,三次维护。这就是传统开发的噩梦。

uniapp 就是来救场的。 它喊出一个口号:「写一套代码,运行在 7 个平台」——iOS、Android、Web、微信小程序、支付宝小程序、抖音小程序、鸿蒙系统。

这一章,我们不急着写代码。先搞清楚两件事:

  1. uniapp 到底是什么? 它是怎么做到「写一套代码,多端运行」的?
  2. 它背后的原理是什么? 为什么这种方式是可行的?

学完这一章,你会对跨平台开发有一个全局认知,下一章就能直接动手创建你的第一个 uniapp 项目了。


🧱 基础:跨平台的本质是什么?

1.1 什么是「跨平台」?

先打个比方。假设你是餐厅老板,想让顾客「用任何手机都能点餐」:

方案 操作方式 成本
方案 A iOS 用户用 iPhone 点,安卓用户用安卓点 需要两套厨师团队
方案 B 做一个网页版,所有手机浏览器都能打开 一套厨师团队,服务所有人

uniapp 就是「方案 B」的思路——写一套代码,中间翻译成各平台能懂的语言

1.2 uniapp 的技术架构

uniapp 不是凭空创造一门语言,它站在巨人的肩膀上:

┌─────────────────────────────────────┐
│           你的代码(Vue 语法)          │  ← 你写的
├─────────────────────────────────────┤
│      uniapp 核心框架(JS 引擎)         │  ← 统一处理
├──────────┬──────────┬───────────────┤
│  iOS    │  Android │   Web/小程序   │  ← 各平台定制
│  SDK    │   SDK    │    适配层      │
└──────────┴──────────┴───────────────┘

用人话解释:uniapp 像一个「翻译官」。你说的是 Vue 语法,翻译官负责把你说的话,翻译成 iOS 听得懂的 Swift、Android 听得懂的 Kotlin、小程序听得懂的 WXML。

1.3 为什么是 Vue?

很多跨平台框架选择 Vue,不是巧合:

Vue 的设计思路是「渐进式」——你想用多少就用多少,从简单页面到复杂应用都能 hold 住。

Python 教学博主来类比一下:

# Python 的「列表推导式」就像 Vue 的「简洁语法」
# 两者都追求:用最少的代码,表达最清晰的意思

# Python 版本
numbers = [1, 2, 3, 4, 5]
squares = [x**2 for x in numbers]

# Vue/uniapp 版本(伪代码)
# squares = numbers.map(x => x * x)

uniapp 选择 Vue,还有一个关键原因:Vue 的生态好,社区活跃,文档健全。学一套语法,能同时对接前端生态和 uniapp 生态,血赚。

1.4 两套开发工具:HBuilderX vs CLI

uniapp 给了你两种开发方式,就像学车可以学「自动挡」或「手动挡」:

工具 特点 适合人群
HBuilderX 图形界面,点按钮就能跑,有可视化调试 新手、小团队、快速开发
CLI 命令行操作,可自定义配置,灵活 熟悉前端的开发者、深度定制需求

我的建议:第一阶段用 HBuilderX,先跑起来再说。等熟悉了,再切换 CLI 不迟。

# 打个不严谨的比方,帮助你理解:
# HBuilderX = 自动挡汽车(简单好上手)
# CLI = 手动挡汽车(灵活但需要更多操作知识)

1.5 跨平台的原理:WebView vs 原生渲染

这是理解 uniapp 的关键。很多人踩坑,就是没搞明白这个。

uniapp 有两种渲染模式:

渲染模式 原理 优点 缺点
WebView 用浏览器内核渲染页面 开发快,兼容性好 性能稍弱,动效复杂的场景卡
原生渲染 直接调用系统原生组件 性能强,体验好 需要针对平台做适配

用人话解释

  • WebView 模式:像在餐厅里用「平板点餐」——餐厅给你一个公版平板,你只能在这个平板的规则里操作。流畅度取决于平板本身,不取决于餐厅厨房。

  • 原生渲染模式:像直接坐在餐桌前跟服务员点菜——服务员是「原生」的,你的体验更直接,但服务员需要懂你的语言。

uniapp 默认使用 WebView 渲染,但如果你的设备支持(如 App 端),可以开启「原生渲染」获得更好性能。

1.6 uniapp 能做什么?不能做什么?

能做
- 简单页面展示类 App(新闻、博客、电商列表)
- 工具类应用(计算器、倒计时、备忘录)
- 小程序生态(微信、支付宝、抖音小程序)
- 企业内部管理系统

不太能做
- 大型游戏(性能要求高的)
- 需要深度系统权限的功能
- 极致性能的图像/视频处理

说白了:uniapp 解决的是「大多数普通 App」的需求,不是所有人。选技术栈之前,先问自己:「我的 App 有没有极致的性能要求?」如果没有,uniapp 完全够用。


🔥 实战:理解跨平台的「翻译」过程

下面我们用 Python 代码来模拟 uniapp 的跨平台编译过程,帮助你理解它到底在干什么。

项目 1:模拟 uniapp 的「代码翻译」机制

# uniapp_compiler.py
# 模拟 uniapp 如何把一套代码「翻译」成各平台

# 第一步:定义你的「通用代码」——就像你用 Vue 写的组件
universal_code = {
"template": "<view class='container'><text>Hello uniapp</text></view>",
"style": ".container { padding: 20px; }",
"script": "export default { data() { return { msg: 'Hello' } } }"
}

# 第二步:模拟「编译」过程——翻译成各平台
def compile_for_platform(code, platform):
"""把通用代码编译成指定平台的代码"""
if platform == "ios":
    # iOS 使用 SwiftUI 语法(简化版模拟)
    return f"""
import SwiftUI
struct ContentView: View {{
var body: some View {{
    Text("{code['script'].split("'")[1]}").padding()
}}
}}
"""
elif platform == "android":
    # Android 使用 Jetpack Compose 语法(简化版模拟)
    return f"""
@Composable
fun MainScreen() {{
Text(text = "{code['script'].split("'")[1]}", modifier = Modifier.padding(20.dp))
}}
"""
elif platform == "web":
    # Web 端输出 Vue 组件
    return f"""
<template>
<div class="container" style="padding: 20px;">
{{{{ message }}}}
</div>
</template>
<script>
export default {{
data() {{
return {{ message: '{code['script'].split("'")[1]}' }}
}}
}}
</script>
"""
else:
    return "Unsupported platform"

# 编译并输出
for platform in ["ios", "android", "web"]:
print(f"=== {platform.upper()} 平台编译结果 ===")
print(compile_for_platform(universal_code, platform))
print()

预期输出

=== IOS 平台编译结果 ===
import SwiftUI
struct ContentView: View {
var body: some View {
    Text("Hello").padding()
}
}

=== ANDROID 平台编译结果 ===
@Composable
fun MainScreen() {
Text(text = "Hello", modifier = Modifier.padding(20.dp))
}

=== WEB 平台编译结果 ===
<template>
<div class="container" style="padding: 20px;">
{{ message }}
</div>
</template>
<script>
export default {
data() {
return { message: 'Hello' }
}
}
</script>

一句话解释:这个脚本演示了 uniapp 的核心思路——「写一次,翻译成多份」。你写的 Vue 代码,经过编译器的「翻译」,变成了 iOS 能懂的 Swift、Android 能懂的 Kotlin、Web 能懂的 HTML/CSS/JS。

项目 2:模拟数据在不同平台间流通

跨平台不仅是「界面翻译」,还有「数据互通」。我们用 Python 模拟一个场景:

# data_sync.py
# 模拟 uniapp 如何处理多端数据同步

import json
from datetime import datetime

# 场景:做一个「校园二手市场」App,卖家发布商品,所有平台都能看到

# 商品数据结构(你定义一次,各端通用)
product = {
"id": "P001",
"title": "二手教材《Python 入门》",
"price": 25.0,
"seller": "计算机学院 小明",
"contact": "138xxxx1234",
"images": ["img1.jpg", "img2.jpg"],
"posted_at": "2024-03-15 10:30:00",
"status": "available"  # available / sold / reserved
}

# 模拟「平台适配层」——把通用数据格式转换成各平台能用的格式

class PlatformAdapter:
"""平台适配器:把统一数据格式转换成各平台专用格式"""

@staticmethod
def for_ios(product):
    """iOS 端格式:Swift 字典风格"""
    return f"""
let product = [
"id": "{product['id']}",
"title": "{product['title']}",
"price": {product['price']},
"seller": "{product['seller']}",
"contact": "{product['contact']}",
"status": "{product['status']}"
]
"""

@staticmethod
def for_android(product):
    """Android 端格式:Kotlin Map 风格"""
    return f"""
val product = mapOf(
"id" to "{product['id']}",
"title" to "{product['title']}",
"price" to {product['price']},
"seller" to "{product['seller']}",
"contact" to "{product['contact']}",
"status" to "{product['status']}"
)
"""

@staticmethod
def for_web(product):
    """Web 端格式:JSON"""
    web_product = product.copy()
    web_product["posted_at"] = product["posted_at"]
    return json.dumps(web_product, indent=2, ensure_ascii=False)

# 测试:同一个商品,三种输出
print("=== iOS 端数据格式 ===")
print(PlatformAdapter.for_ios(product))

print("=== Android 端数据格式 ===")
print(PlatformAdapter.for_android(product))

print("=== Web 端数据格式 ===")
print(PlatformAdapter.for_web(product))

# 模拟「数据校验」——各平台上传数据前先校验格式
def validate_product(product):
"""校验商品数据格式(统一校验逻辑)"""
errors = []

if not product.get("title"):
    errors.append("商品标题不能为空")
if not product.get("price") or product["price"] < 0:
    errors.append("商品价格必须大于 0")
if not product.get("seller"):
    errors.append("卖家信息不能为空")
if product.get("status") not in ["available", "sold", "reserved"]:
    errors.append("商品状态必须是 available/sold/reserved")

return errors

# 测试校验
test_product = {"title": "", "price": -10, "status": "invalid_status"}
errors = validate_product(test_product)
print("=== 数据校验测试 ===")
print(f"错误数量: {len(errors)}")
for error in errors:
print(f"  - {error}")

预期输出

=== iOS 端数据格式 ===
let product = [
"id": "P001",
"title": "二手教材《Python 入门》",
"price": 25.0,
"seller": "计算机学院 小明",
"contact": "138xxxx1234",
"status": "available"
]

=== Android 端数据格式 ===
val product = mapOf(
"id" to "P001",
"title" to "二手教材《Python 入门》",
"price" to 25.0,
"seller" to "计算机学院 小明",
"contact" to "138xxxx1234",
"status" to "available"
)

=== Web 端数据格式 ===
{
"id": "P001",
"title": "二手教材《Python 入门》",
"price": 25.0,
"seller": "计算机学院 小明",
"contact": "138xxxx1234",
"posted_at": "2024-03-15 10:30:00",
"status": "available"
}

=== 数据校验测试 ===
错误数量: 3
- 商品标题不能为空
- 商品价格必须大于 0
- 商品状态必须是 available/sold/reserved

一句话解释:uniapp 的「数据层」是统一的,不管用户用 iPhone 还是安卓,数据结构只有一份。你只写一次校验逻辑,所有平台都生效——这就是「写一套代码」的真实含义。

项目 3:组合实战——做一个跨平台配置中心

# config_center.py
# 模拟 uniapp 项目中的「统一配置中心」
# 场景:你做了一个 App,需要在「开发环境」「测试环境」「生产环境」之间切换

import json
from enum import Enum

class Env(Enum):
"""环境枚举"""
DEV = "development"
TEST = "testing"
PROD = "production"

class ConfigCenter:
"""统一配置中心:管理多环境的配置"""

def __init__(self, env: Env):
    self.env = env
    self.config = self._load_config()

def _load_config(self):
    """根据环境加载对应配置"""
    configs = {
        Env.DEV: {
            "api_base": "http://localhost:3000/api",
            "debug": True,
            "log_level": "DEBUG",
            "timeout": 5000,
            "enable_cache": False,
            "mock_data": True  # 开发环境用模拟数据
        },
        Env.TEST: {
            "api_base": "https://test-api.yourapp.com/api",
            "debug": True,
            "log_level": "INFO",
            "timeout": 10000,
            "enable_cache": True,
            "mock_data": False
        },
        Env.PROD: {
            "api_base": "https://api.yourapp.com/api",
            "debug": False,
            "log_level": "WARNING",
            "timeout": 15000,
            "enable_cache": True,
            "mock_data": False
        }
    }
    return configs[self.env]

def get(self, key):
    """获取配置项"""
    return self.config.get(key)

def generate_platform_config(self, platform):
    """生成各平台专用配置"""
    base = self.config.copy()

    if platform == "ios":
        base["platform"] = "iOS"
        base["native_module"] = "uni.UNIPaysModule"
    elif platform == "android":
        base["platform"] = "Android"
        base["native_module"] = "io.dcloud.feature.payment.WechatPay"
    elif platform == "mp-weixin":
        base["platform"] = "WeChat MiniProgram"
        base["native_module"] = "wx.requestPayment"
    else:
        base["platform"] = "Unknown"
        base["native_module"] = None

    return base

def __str__(self):
    return f"ConfigCenter({self.env.value})"

# 使用示例
print("=" * 50)
print("场景:一键切换环境配置,生成各平台配置清单")
print("=" * 50)

# 切换到开发环境
dev_config = ConfigCenter(Env.DEV)
print(f"\n当前环境: {dev_config}")
print(f"API 地址: {dev_config.get('api_base')}")
print(f"调试模式: {dev_config.get('debug')}")
print(f"模拟数据: {dev_config.get('mock_data')}")

print("\n--- 生成各平台配置 ---")
for platform in ["ios", "android", "mp-weixin"]:
p_config = dev_config.generate_platform_config(platform)
print(f"\n【{platform}】")
print(json.dumps(p_config, indent=2, ensure_ascii=False))

# 一键切换到生产环境
print("\n" + "=" * 50)
print("切换到生产环境(运维操作,一行代码)")
print("=" * 50)

prod_config = ConfigCenter(Env.PROD)
print(f"\n当前环境: {prod_config}")
print(f"API 地址: {prod_config.get('api_base')}")
print(f"调试模式: {prod_config.get('debug')}")
print(f"模拟数据: {prod_config.get('mock_data')}")

预期输出

==================================================
场景:一键切换环境配置,生成各平台配置清单
==================================================

当前环境: ConfigCenter(development)
API 地址: http://localhost:3000/api
调试模式: True
模拟数据: True

--- 生成各平台配置 ---
{
"api_base": "http://localhost:3000/api",
"debug": true,
"log_level": "DEBUG",
"timeout": 5000,
"enable_cache": false,
"mock_data": true,
"platform": "iOS",
"native_module": "uni.UNIPaysModule"
}

{
"api_base": "http://localhost:3000/api",
"debug": true,
"log_level": "DEBUG",
"timeout": 5000,
"enable_cache": false,
"mock_data": true,
"platform": "Android",
"native_module": "io.dcloud.feature.payment.WechatPay"
}

{
"api_base": "http://localhost:3000/api",
"debug": true,
"log_level": "DEBUG",
"timeout": 5000,
"enable_cache": false,
"mock_data": true,
"platform": "WeChat MiniProgram",
"native_module": "wx.requestPayment"
}

==================================================
切换到生产环境(运维操作,一行代码)
==================================================

当前环境: ConfigCenter(production)
API 地址: https://api.yourapp.com/api
调试模式: False
模拟数据: False

一句话解释:这个配置中心的思路,就是 uniapp「条件编译」功能的简化版。你写一套配置,根据环境变量和目标平台,自动生成对应代码——不用维护三套代码库,一个项目搞定。


💪 进阶:新手最容易踩的坑

❌ 坑 1:以为 uniapp 能解决所有性能问题

# ❌ 错误理解:用了 uniapp,性能问题就不存在了
# 真相:uniapp 只是帮你少写代码,不是不写代码
# 性能优化还是得自己做

# 举个例子:加载 10000 条数据
bad_code = """
<!-- 一次性渲染 10000 条——卡死你 -->
<template>
<view>
<view v-for="item in allItems">{{ item.name }}</view>
</view>
</template>
"""

good_code = """
<!-- 正确做法:分页 + 懒加载 -->
<template>
<uni-list>
<uni-list-item v-for="item in visibleItems" :key="item.id">
  {{ item.name }}
</uni-list-item>
</uni-list>
<button @click="loadMore">加载更多</button>
</template>
"""

说白了:uniapp 是「省力工具」,不是「性能魔法」。大数据量、复杂动效,该优化的还是要优化。

❌ 坑 2:混淆「跨平台能力」和「平台差异」

# ❌ 错误写法:假设所有平台 API 行为完全一致
def upload_image(image_path):
# 微信小程序没有这个方法,会报错!
wx.chooseImage({count: 1})
# ... 上传逻辑

# ✅ 正确写法:使用条件编译或 uni API 统一封装
def upload_image(image_path):
# uni.chooseImage 是 uniapp 统一 API,各平台都支持
uni.chooseImage({
    count: 1,
    success: (res) => {
        # 统一上传逻辑
        uni.uploadFile({
            url: API_BASE + '/upload',
            filePath: res.tempFilePaths[0]
        })
    }
})

注意:uniapp 提供「统一 API」封装了平台差异,但不是所有平台特性都能封装。遇到地图、支付、推送这种平台强相关功能,要查文档确认。

❌ 坑 3:直接用 width: 750rpx 当作万能方案

# ❌ 错误理解:rpx 是万能的,任何场景都适用
# 真相:rpx 是为了适配不同屏幕尺寸,但有局限性

# ❌ 错误写法:在大屏上显示正常,小屏上超出边界
box = """
.view {
width: 700rpx;  /* 小屏手机可能显示不下 */
height: 500rpx;
}
"""

# ✅ 正确做法:用 flex 布局 + max-width 限制
correct_box = """
.view {
width: 100%;
max-width: 700rpx;  /* 最大宽度限制 */
height: auto;
box-sizing: border-box;
}
"""

❌ 坑 4:忽略条件编译,导致平台专属代码报错

# ❌ 错误写法:在 H5 端调用小程序专属 API
def onShareAppMessage():
# 小程序有这个功能,H5 没有!
return wx.showShareMenu()  # H5 端直接报错

# ✅ 正确写法:用条件编译,只在有该功能的平台执行
correct = """
// #ifdef MP-WEIXIN
wx.showShareMenu()
// #endif

// #ifndef H5
// 这里写非 H5 平台的代码
// #endif
"""

调试技巧:uniapp 的条件编译用 // #ifdef 语法,写完代码后,用 HBuilderX 的「运行到不同平台」功能逐个测试。

❌ 坑 5:以为学会 Vue 就能精通 uniapp

# ❌ 错误理解:Vue 会了,uniapp 就会了
# 真相:uniapp 有自己的「扩展组件」和「API」,Vue 语法只是基础

# uniapp 特有概念(Vue 里没有):
# - pages.json(路由配置)
# - manifest.json(应用配置)
# - uni.xxx API(支付、推送、扫码...)
# - nvue 页面(原生渲染)
# - 条件编译(#ifdef / #ifndef)

性能小贴士:合理使用 onReachBottom 替代watch

# ❌ 低效写法:用 watch 监听分页变化
"""
watch: {
page() {
    this.loadMore();  // 每次 page 变化都请求
}
}
"""

# ✅ 高效写法:用 onReachBottom 监听触底事件
"""
onReachBottom() {
if (!this.loading && this.hasMore) {
    this.page++;
    this.loadMore();
}
}
"""

# onReachBottom 是页面级别的事件,只有用户滑到底部才触发
# watch 是数据级别的,任何变化都会触发,可能导致不必要请求

调试技巧:用 console.info 替代 console.log

# uniapp 提供增强版日志,能显示更多信息
debug_code = """
// 普通日志(发布后会被移除)
console.log('普通日志');

// info 日志(发布后保留)
console.info('调试信息', { page: 1, data: res });

// 警告(提示潜在问题)
console.warn('这个 API 在某些平台表现不一致');

// 错误(代码有 bug)
console.error('请求失败', error);
"""

# 技巧:在关键节点打日志,用 uni.showToast 配合调试
toast_debug = """
uni.request({
url: 'xxx',
success: (res) => {
    console.info('请求成功', res);
    if (res.data.code !== 0) {
        uni.showToast({ title: '数据异常', icon: 'none' });
    }
},
fail: (err) => {
    console.error('请求失败', err);
    uni.showToast({ title: '网络错误', icon: 'error' });
}
});
"""

✏️ 练习题

练习 1(2 分钟):修改环境配置

# 已知以下配置对象,修改它使 api_base 指向测试环境
config = {
"api_base": "https://api.example.com",
"debug": False,
"timeout": 15000
}
  • 预期输出:打印出修改后的 api_base,值应为 "https://test-api.example.com"
  • 提示:直接赋值即可

练习 2(3 分钟):添加平台判断

# 在以下代码中添加 if 判断:当 platform 为 "ios" 时,输出 "苹果平台"

def check_platform(platform):
# 你的代码
pass

check_platform("ios")  # 预期输出:"苹果平台"
check_platform("android")  # 预期输出:"其他平台"
  • 提示:用 if platform == "ios" 判断

练习 3(5 分钟):用适配器模式转换数据

# 已有商品数据,仿照项目 2 的 PlatformAdapter,
# 新增一个 "mp-alipay"(支付宝小程序)的输出格式

product = {
"id": "P002",
"title": "二手自行车",
"price": 200.0,
"seller": "机械学院 小红"
}

# 支付宝小程序格式要求:
# - 用 my.xxx API(不是 wx.xxx)
# - 额外字段:alipay_trade_no(模拟交易号)
  • 预期输出:打印出支付宝小程序格式的商品数据
  • 提示:参考项目 2 的 for_wechat 写法,替换 wxmy

练习 4(5 分钟):组合配置与环境

# 已知 Env 枚举和 ConfigCenter 类,
# 添加一个新环境 "STAGING"(预发布环境),
# 要求:API 指向 test-api,debug=True,mock_data=False

class Env(Enum):
DEV = "development"
TEST = "testing"
PROD = "production"
# 添加 STAGING
  • 预期输出:能成功创建 ConfigCenter(Env.STAGING) 并获取正确配置
  • 提示:在 configs 字典中添加新键值对

练习 5(10 分钟):分析报错原因

# 用户运行代码后,控制台报错:
# "TypeError: Cannot read property 'title' of undefined"

# 相关代码:
data = fetch_product_from_server()  # 假设这个函数返回了 undefined
print(data.title)  # 第 2 行报错

# 问题:请分析原因,并写出修复代码
  • 预期输出:修复后,无论 fetch_product_from_server 返回什么,代码都不会崩溃
  • 提示if data is Nonedata and data.title

作业:做一个「跨平台 API 调试工具」

需求描述:做一个命令行工具,模拟 uniapp 的「统一 API 调用 + 平台适配」功能。用户输入一个接口名称,工具自动生成各平台的调用代码。

功能点
1. 支持 4 个 API:getUserInfo(获取用户信息)、login(登录)、uploadFile(上传文件)、pay(支付)
2. 输入 API 名称后,自动生成 iOS(Swift)、Android(Kotlin)、Web(JavaScript)三份代码
3. 每份代码用注释标注「uniapp 统一 API」和「平台专属实现」的区别

加分项
1. 支持从 JSON 文件读取 API 列表
2. 支持指定输出目录,自动生成 .swift.kt.js 文件

验收标准
- 运行 python api_debugger.py getUserInfo 能输出三份代码
- 代码有中文注释,解释每一步在干什么
- 能实际运行(语法正确)

提交方式:评论区贴代码或 GitHub 链接


📚 总结

这一章我们学了 3 个核心点

  1. uniapp 是「翻译官」:你写 Vue,它翻译成各平台代码,实现「写一套,跑七端」
  2. 两种渲染模式:WebView(快但卡)、原生渲染(流畅但需要适配)
  3. 开发工具二选一:新手用 HBuilderX 快速上手,熟悉后用 CLI 深度定制

下一章预告

现在你知道了 uniapp 是什么、怎么工作的。但「知道」和「做到」之间,还差一个「第一个项目」。

下一章,我们会手把手创建第一个 uniapp 项目,从安装工具到运行「Hello World」,完整走一遍流程。学完下一章,你就能写出真正可以跑在手机上的代码了。


推荐资源

  1. uniapp 官方文档 —— 最好的教程,文档即教程
  2. Vue3 官方教程 —— uniapp 的语法基础
  3. 《跨平台桌面应用开发》—— 理解跨平台思想的书,有助于举一反三

互动钩子

你有没有遇到过「做了一个 App,结果要维护三套代码」的情况?或者你现在正在用其他跨平台框架?评论区聊聊,老粉优先回复!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。