很多人第一次听说 HBuilderX,是在搜“用什么工具写 uni-app”或者“有没有比 VS Code 更轻量的前端编辑器”的时候。我的答案一直很明确:如果你做 uni-app、做多端小程序、做 Vue2/Vue3 的跨端项目,HBuilderX 是绕不开的第一梯队选择。它不只是一款编辑器,更是一套把“写代码、调试、打包、发布”串在一起的开发工作台,尤其内置浏览器 debug 功能,解决了很多前端新手“代码写完不知道去哪看效果”的痛点。
这篇内容不是官方文档的复读,而是我带着一个真实的小项目,从安装、建项目、写页面、调接口、多端编译到常见问题排查,完整走一遍的记录和踩坑总结。适合刚接触 HBuilderX 的编程学习者,也适合正在犹豫要不要从别的编辑器切换过来的老手。
1. 为什么选择HBuilderX:这个IDE到底解决了什么问题
1.1 从编辑器到多端开发台的定位变化
很多人对 IDE 的印象还停留在“一个能写代码的文档编辑器”。HBuilderX 不一样的地方在于,它把编辑器和工具链整合到了一起。官方定位是“数字开发者工具”,但对前端和跨端开发来说,更准确的理解是:它内置了uni-app的编译链路。
用大白话说,你写一套.vue文件,HBuilderX 能把它编译成能在微信小程序、支付宝小程序、H5、App 和快应用上运行的代码。这个过程不需要你自己去配置 webpack、不需要自己处理小程序项目的app.json、project.config.json这些底层文件,全都在可视化界面里完成。
我刚开始用的时候其实很怀疑:这种“全家桶”式的工具,会不会比我手动配置 Tailwind + Vite + uni-app CLI 更麻烦?用了一段时间后的感觉恰恰相反。对于大多数业务项目,HBuilderX 省掉的是最枯燥的工程化配置环节,让你把注意力集中到业务代码本身。
1.2 五大核心优势拆解
结合我用的这几个项目,HBuilderX 最核心的五个优势是:
- 启动速度和内存占用。HBuilderX 的启动比 VS Code 快很多,项目大一点也不会卡。我试过同时开两个 HBuilderX 窗口和一个浏览器调试页面,内存占用依然可控。
- 内置浏览器和真机调试无缝衔接。这是它比普通编辑器强得多的地方,后面我会专门拆解 debug 流程。
- uni-app 语法和 API 提示完善。写
uni.request、uni.navigateTo这类 API 的时候自动补全非常舒服,几乎不需要翻文档。 - 可视化打包发布。HBuilderX 自带的发行功能,能够一键生成微信小程序、H5 和 App 的资源包。比如微信小程序,它会自动生成
dist/build/mp-weixin目录,你只需要在微信开发者工具里导入这个目录就行。 - 内置终端和 Git 集成。虽然它不如 VS Code 的插件生态丰富,但日常
npm install、git commit这些操作都能在界面里完成,不需要来回切换。
我认识的一些初学者,总喜欢先装一堆插件再写代码,结果光配置环境就劝退了。用 HBuilderX 的话,基本是“下载解压即用”,官方都帮你配好了。
1.3 适用人群和场景判断
到底哪些人适合用 HBuilderX?我认为主要是这三类:
- 以 uni-app 为主要技术栈的前端开发者,比如公司需要同时维护小程序、H5、App。
- 初学编程、想做跨端应用但不想碰复杂工程化配置的新手。
- 需要快速验证原型,比如两天内就要跑通一个带登录、列表、详情页的演示项目。
如果你的项目是一个纯 Vue 后台管理系统,或者是一个深度定制 webpack/Vite 的 PC 端应用,HBuilderX 反而不如 VS Code 灵活。选工具要看场景,我个人的原则是:终端侧和跨端侧优先 HBuilderX,纯 Web 工程化优先 VS Code。
2. 环境搭建与项目初始化:一步步把开发环境跑起来
2.1 安装与首次配置细节
HBuilderX 的安装非常简单,官方下载对应系统版本,解压到本地即可。这里有几个容易被忽略的细节:
- 解压路径不要带中文和空格,避免后续文件路径出问题。
- 首次启动如果提示“软件已损坏”或者弹出类似安全校验的提示,这是 macOS 对“未公证应用”的常规拦截,需要在“系统设置”—“隐私与安全性”中手动允许。
- 启动后建议先登录账号,虽然不登录也能用基础功能,但登录后可以同步插件、使用云打包等云端服务,很多项目都要用到云打包。
打开后的界面布局我建议先做一次定制:把默认的资源管理器字体调大,开启“自动保存”选项,再在“工具—设置—编辑器”里把缩进改成 2 空格。Vue 官方风格就是 2 空格缩进,HBuilderX 里的默认代码提示也按这个规范来。
2.2 新建uni-app项目的三种方式
在 HBuilderX 里新建项目,分别有“空项目”“uni-app 项目”“uni-app cli 项目”几个选择。我推荐的做法是:进入文件菜单,选择新建项目,选择 uni-app 模板。
打开新建向导后,最关键的两个选项是模板和版本。模板分为“默认模板”“Hello uni-app”“登录模板”等。“Hello uni-app”里附带了很多示例页面,比如下拉刷新、图片上传、富文本解析,适合作为学习参考,但正式开发时不建议在这个基础上去改,因为有很多冗余代码。默认模板更适合从零开始的项目构建。
还有一个容易混淆的版本选项:Vue2 还是 Vue3?如果公司项目是 2025 年前的存量项目,大概率是 Vue2;如果是新启动的项目,我建议优先 Vue3。但如果你是学习 Vue2 的语法,想要找一套能直接跑通的代码, Vue2 模板依然是经典的教学方式,因为社区里大量的旧教程、老项目、插件都是 Vue2 语法,新手照着抄更容易跑通。
2.3 Vue2还是Vue3:实战项目选型对比
下面这个对比是基于我自己的项目和踩坑经验做的,不是官方参数表,但能帮你快速决策:
| 对比维度 | Vue2(Options API) | Vue3(Composition API) |
|---|---|---|
| 学习成本 | 低,文档和教程最多 | 中,需要理解setup和响应式 API |
| 项目兼容性 | 大量老插件只支持 Vue2 | 新插件基本都优先支持 Vue3 |
| 运行性能和代码组织 | 项目大了逻辑容易分散 | composables按功能聚合逻辑,更好维护 |
| HBuilderX 支持 | 稳定 | 稳定 |
| 适合人群 | 初学者、维护老项目 | 新项目、有一定经验的开发者 |
我这次实战项目为了贴近大多数人的学习路径,选的是 Vue2 默认模板 + uni-app,这样你不管是在 B站还是博客里看到相关的教程,代码都是能对应上的。
2.4 项目目录结构解读
新建项目后,你会看到这样的目录结构:
├── pages │ └── index │ └── index.vue ├── static ├── unpackage │ └── dist ├── App.vue ├── main.js ├── manifest.json ├── pages.json └── uni.scss刚接触的人最容易搞混的是pages.json。它不是给 Vue 页面用的 JSON,而是整个 uni-app 的全局路由和页面配置。每新增一个页面,都需要在pages.json里注册,否则编译后页面无法访问。
manifest.json管的是应用级别的配置,比如应用名称、AppID、小程序 AppID、App 图标、权限说明等。多端发布时的差异配置基本都在这里。
App.vue是根组件,适合放全局生命周期和公共样式。注意:这个文件里的<template>通常只留一个占位视图,所有页面是放在 pages 目录下属的组件里的。
uni.scss是全局样式变量文件,你在这里定义的变量、样式,可以直接被页面里的style lang="scss"块引用,不需要额外 import 一个公共样式文件。
3. vue2实战项目核心实现:从页面到接口的完整链路
3.1 页面结构与路由配置
我用一个常见的“商品列表 + 商品详情 + 购物车”的 mini 电商项目来做演示。目标很简单:跑通一个完整的业务链路。
第一步,在pages.json里配置三个页面:
{ "pages": [ { "path": "pages/index/index", "style": { "navigationBarTitleText": "首页" } }, { "path": "pages/detail/detail", "style": { "navigationBarTitleText": "商品详情" } }, { "path": "pages/cart/cart", "style": { "navigationBarTitleText": "购物车" } } ] }页面跳转我推荐用uni.navigateTo,因为它的生命周期符合“有返回按钮”的导航模式。比如从首页跳详情页:
uni.navigateTo({ url: '/pages/detail/detail?id=1001' });详情页接收参数用的是onLoad(options),这个 API 在 Vue2 和 Vue3 中一致:
export default { data() { return { goodsId: '' }; }, onLoad(options) { this.goodsId = options.id; this.fetchDetail(); } };这里有一个新手经常踩的坑:页面跳转的url必须以/开头,否则在浏览器端没问题,但在小程序端会出现路径解析错误,页面白屏。我当初就因为这个浪费了半天。
3.2 状态管理与接口请求封装
Vue2 的 uni-app 项目,官方默认的状态管理方案是 Vuex。我在store目录下建了index.js,用来管理购物车的商品数量:
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const store = new Vuex.Store({ state: { cartCount: 0 }, mutations: { incrementCartCount(state) { state.cartCount++; } }, actions: { addToCart({ commit }) { commit('incrementCartCount'); } } }); export default store;然后在main.js里挂载:
import Vue from 'vue'; import App from './App.vue'; import store from './store'; Vue.prototype.$store = store; App.mpType = 'app'; const app = new Vue({ ...App }); app.$mount();接口请求封装是我觉得整个项目里最值得拆解的模块。所有请求我都放进utils/request.js,用Promise包一层uni.request:
const BASE_URL = 'https://api.example.com/api'; function request(options = {}) { return new Promise((resolve, reject) => { uni.request({ url: BASE_URL + options.url, method: options.method || 'GET', data: options.data || {}, header: { 'Content-Type': 'application/json', // 这里可以放 token,比如 options.header.Authorization }, success: (res) => { // 业务状态码判断 if (res.data.code === 200) { resolve(res.data.data); } else { uni.showToast({ title: res.data.message || '请求出错', icon: 'none' }); reject(res.data); } }, fail: (err) => { uni.showToast({ title: '网络异常,请稍后重试', icon: 'none' }); reject(err); } }); }); } export default request;为什么封装成 Promise?因为这样你在页面里写起来很舒服:
import request from '@/utils/request.js'; async fetchDetail() { const data = await request({ url: '/goods/detail', data: { id: this.goodsId } }); this.goodsInfo = data; }@/是 HBuilderX 默认配置的路径别名,指项目根目录。在 Vue2 项目里它是默认生效的,不需要像纯 Vue CLI 项目那样去配置resolve.alias。
3.3 组件化开发与常用API整理
开发完整项目时,我会把常见的 UI 块拆成组件。比如商品卡片组件components/goods-card/goods-card.vue:
<template> <view class="goods-card" @click="goDetail"> <image :src="goods.cover" mode="aspectFill" class="cover" /> <view class="title">{{ goods.title }}</view> <view class="price">¥{{ goods.price }}</view> </view> </template> <script> export default { name: 'GoodsCard', props: { goods: { type: Object, required: true } }, methods: { goDetail() { uni.navigateTo({ url: `/pages/detail/detail?id=${this.goods.id}` }); } } }; </script>在页面中引入组件后,需要components字段声明。Vue2 里的规范是这样:
import GoodsCard from '@/components/goods-card/goods-card.vue'; export default { components: { GoodsCard } };这里有个 uni-app 和普通 Vue 写法之间的区别:普通 Vue 项目的组件在父组件里引入后,可以直接在<template>中使用<goods-card>或<GoodsCard>,但 uni-app 在小程序端编译时,推荐统一使用goods-card短横线命名方式,避免大小写编译问题。
常用 API 我整理成一个速查清单:
uni.request:网络请求。uni.navigateTo:跳转页面,保留原页面。uni.redirectTo:关闭当前页面并跳转。uni.switchTab:跳转到 tabBar 页面(注意:不能带参数)。uni.showToast/uni.showModal:轻提示和弹窗。uni.setStorageSync/uni.getStorageSync:本地同步存储。uni.getSystemInfoSync:获取设备信息,比如屏幕宽高、状态栏高度。
这些 API 是小程序和 App 端都通用的,属于跨端开发的“语法糖”。你只需要记住它们的名字,HBuilderX 的语法提示会帮你把参数列出来。
3.4 生命周期与差异化场景适配
uni-app 的页面生命周期和普通 Vue 页面不太一样。它除了created、mounted这类 Vue 内置生命周期,还增加了小程序风格的生命周期:onLoad、onShow、onReady、onHide、onUnload。
我经常用onShow做回到页面时的数据刷新。比如购物车页面,用户从详情页点击加购后返回,需要重新计算购物车数量。写在onShow里比created更合适,因为created只在页面首次创建时触发一次,而onShow每次页面显示都会触发。
onShow() { this.cartCount = uni.getStorageSync('cartCount') || 0; }如果你要拿页面尺寸来做自适应布局,用uni.getSystemInfoSync()时要注意:在小程序端返回的windowWidth以逻辑像素为准,单位是px,而在 App 端返回值可能包含不同比例。最保险的做法是尺寸相关计算统一用upx或rpx,因为 uni-app 会自动编译适配。
4. 内置浏览器debug:从零到一学会调试uni-app
4.1 启动内置浏览器的完整流程
HBuilderX 内置浏览器可以用来直接预览编译后的 H5 页面,也支持断点调试,这是我强烈推荐新手最先掌握的技能。
操作路径我一步步说:
- 在 HBuilderX 工具栏找到“运行”按钮,下拉选择
运行到浏览器—Chrome。 - 首次运行,HBuilderX 会自动编译 uni-app 项目,然后打开一个内置的浏览器窗口。
- 如果浏览器没有自动弹出,查看控制台是不是有编译错误,尤其是
pages.json写错时,编译会直接失败,并提示具体报错位置。
内置浏览器和外部浏览器的最大区别,是它帮你提前内置了“uni-app 的 H5 运行时环境”,所以uni.request、uni.setStorage这些 API 都能正常工作。如果用普通浏览器直接打开static下的 HTML,那就是另一套逻辑了。
在启动前,你还可以在 manifest.json 的 H5 节点下设置开发端口:
{ "h5": { "devServer": { "port": 8080 } } }如果你同时开了多个 HBuilderX 项目,端口冲突特别常见。把端口固定下来能省很多事。
4.2 断点调试、Console与Network实战
内置浏览器调试的核心优势在于:你可以像使用 Chrome DevTools 一样,直接在源码里打断点。
在编辑器的代码行号左侧点击,就能插入一个圆形的断点。然后在点击页面上的某个按钮,比如触发商品详情请求,代码就会停在断点处,此时可以查看当前作用域里的变量值、调用栈。
TypeScript 风格的debugger语句也可以:
async fetchDetail() { const params = { id: this.goodsId }; debugger; // 在这里暂停 const data = await request({ url: '/goods/detail', data: params }); this.goodsInfo = data; }需要留意的是:断点只能调试 JS 逻辑,不能直接在<template>的插值表达式中打断点。想查看页面渲染的数据,要么在methods里打 log,要么在 Console 里执行this.$data查看当前页面实例。
Network 面板在调试接口时很有用。打开“网络”标签页,刷新页面,能看到所有发出的请求、请求头、响应体。我排查接口报错时,第一件事是确认请求有没有发出去,第二件事看响应里的status code和业务code。如果请求根本没发出,八成是BASE_URL配错或者在 manifest.json 的 H5 节点里没配置跨域。
内置浏览器还支持移动端模拟。工具栏里的设备模拟器可以切换成 iPhone X、iPad 等机型,默认视口大小会自动适配。切换后点击某个 UI 元素,右侧还会显示对应的 DOM 结构,方便定位样式问题。
4.3 真机调试与浏览器调试的差异
内置浏览器调试方便归方便,但它始终是 H5 环境。有些能力,比如扫码、蓝牙、NFC、扫码枪对接,必须真机调试才能验证。
HBuilderX 的真机调试流程是:手机连接电脑,确保开启 USB 调试模式,然后在运行菜单里选择“运行到手机或模拟器”。首次连接会自动安装基座 App,这个基座 App 是 uni-app 官方提供的测试壳,里面集成了大部分原生能力。
我用 Chrome 调试从来没遇到过的两个问题,在真机调试时经常出现:
- 真机基座 App 版本和 HBuilderX 版本不一致,导致
uni对象上某些 API 不存在。强制方案是升级 HBuilderX 并重新运行,让基座自动更新。 - 安卓和 iOS 对安全协议的处理不同,
http明文请求在 iOS 上是默认被禁止的。开发阶段真机调试如果接口走http,需要到manifest.json — App — 其他设置里关闭“iOS 平台禁用 http”或配置 ATS 白名单。
所以我的习惯是:UI 和业务逻辑先用内置浏览器调试,涉及硬件能力和平台差异的部分再上真机。这样效率最高。
5. 多端编译与发布:一套代码跑五个端
5.1 微信小程序、H5、App打包流程
调试通过后,真正开始面向生产环境运行时,走的就是“发行”流程。
微信小程序发行步骤:
- 在
manifest.json的小程序节点填入你的微信小程序AppID。 - 点击菜单栏
发行—小程序-微信。 - 编译完成后,HBuilderX 会在
unpackage/dist/build/mp-weixin目录下生成小程序代码。 - 打开微信开发者工具,选择导入项目,目录指向上述位置。
这一步我见过的最常见误区是:导入的时候把整个unpackage目录选进去了。正确的目录应该是包含app.json、project.config.json的那一层,也就是unpackage/dist/build/mp-weixin。
H5 发行更简单,点击发行—网站-H5手机版,生成unpackage/dist/build/h5目录。这个目录就是一个纯静态文件夹,可以部署到 Nginx、OSS 或者 CDN。如果要用 web 服务器托管,还要注意单页应用的路由模式:hash 模式默认直接可用,history 模式需要 Nginx 做try_files回退配置。
App 发行分两种:云打包和本地打包。云打包是 HBuilderX 官方提供的打包服务,你只需要在云端勾选包名、证书、图标等参数,它会在云端完成原生项目编译和签名。本地打包则需要你本地安装 Android Studio 或 Xcode,适合需要深度定制原生能力或公司已有原生项目的场景。个人开发者和中小团队,云打包完全足够。
如果你还没有开通 DCloud 开发者认证,云打包会先引导你完成实名认证,这是正常流程,不是额外收费。
5.2 条件编译与平台差异处理
一套代码跑多端,最大的挑战来自平台差异。uni-app 提供了“条件编译”这个利器,让你可以在同一份代码里针对不同平台写不同逻辑。
条件编译的语法很简单。以 js 代码块为例:
// #ifdef H5 console.log('这个只在 H5 端执行'); // #endif // #ifndef H5 console.log('这个只在非 H5 端执行'); // #endif以 CSS 为例:
/* #ifdef MP-WEIXIN */ .login-btn { margin-top: 20rpx; } /* #endif */ /* #ifdef H5 */ .login-btn { margin-top: 30px; } /* #endif */我在这里踩过一个比较隐蔽的坑:H5和H5-MP的大小写要严格区分。官方条件的规范是:
H5:H5 平台。MP-WEIXIN:微信小程序。APP-PLUS:App 平台,也写作APP。MP-ALIPAY:支付宝小程序等。
条件编译的注释标记必须紧跟代码,前后不能有其他字符,否则会导致编译失败。遇到这种问题,先在编辑器里确认代码块有没有被注释标记包裹,再去排查括号。
还有一个更实用的差异是window对象。浏览器端能直接使用window,但小程序环境没有window。如果你在某个 js 工具库里有如下代码:
const width = window.innerWidth;这段代码在小程序端会直接报window is not defined。正确做法是用条件编译包裹:
// #ifdef H5 const width = window.innerWidth; // #endif或者直接用 uni-app 的 API:
const { windowWidth } = uni.getSystemInfoSync();这个方法两端的输出一致,优先级更高。
5.3 多端发布的避坑清单
我直接把我做过的几个生产项目里踩到的坑列成清单,你可以直接对照检查:
- App 端 CSS 单位最好统一用
rpx,完全兼容 px 的还有半年兼容逻辑,但新项目直接用 rpx 最省事。 - 小程序端不支持在
style里写动态backgroundImage赋值链接,需要先构建一个 base64 或放到static下再引用。 - 发布小程序前,需要在微信公众平台把服务器域名配置到合法域名列表,否则接口请求全部被拦。
- H5 部署到子路径时,需要在
manifest.json的 H5 节点设置base路径,否则资源加载会出现 404。 - App 云打包前,务必备份好证书和 key 信息,丢失后应用无法更新上架。
- 所有页面图片尺寸适配,建议用
image组件并传mode="widthFix",避免不同宽高比时图片显示变形。
打包完成后,我会统一检查三件套:manifest.json里的应用名称、图标和启动图是否都被正确替换成业务信息。很多新手打包完发现桌面图标还是默认的 uni-app logo,就是没有上传自己的图标文件。
6. 常见问题与排查技巧实录
6.1 高频问题速查表
我把这几年的高频问题按“现象—原因—解决”整理成一个速查表。这里面的问题,我几乎都快形成条件反射了:
| 现象 | 常见原因 | 解决思路 |
|---|---|---|
| 内置浏览器白屏 | pages.json 路由路径写错 | 检查编译日志,确认首个页面路径 |
| 运行后提示找不到 AppID | manifest.json 没填小程序 AppID | 填入真实 AppID,或使用测试号 |
| 编译成功但接口请求失败 | 跨域或域名未配置 | H5 端配 proxy,小程序端配合法域名 |
| 样式在小程序端错乱 | 使用了*选择器或标签选择器 | 修改为类名选择器,避免全局通配 |
uni对象报 undefined | HBuilderX 版本过低或引入了异常插件 | 升级工具,禁用冲突插件 |
| 页面图片不显示 | 图片路径用了绝对路径未加/static | 确保图片放在 static 目录并用项目相对路径 |
| 云打包提示证书过期 | 证书到期 | 重新生成证书并上传 |
| 真机基座无法连接 | 手机没有开启 USB 调试 | 检查 USB 模式并重新插拔 |
| 内置终端运行 npm 报错 | 终端路径没配置 | 在设置中指定 npm 的全局路径 |
下面挑几个最有代表性的详细说说。
6.2 从报错到解决的典型排查过程
案例一:内置浏览器白屏。
出现白屏时,第一步不是改代码,而是先看“控制台”面板的编译输出。有一次我遇到白屏,控制台提示Cannot read property 'call' of undefined。这个报错很笼统。我先注释了入口页里所有新增的 import,逐个恢复,最后定位到是我在store/index.js里写了一个import store from './store'的循环引用,导致编译模块加载顺序异常。
解决办法是把 store 里的 Vuex 初始化改成独立文件引用,并在main.js里重新按顺序导入。
案例二:H5 调试时接口 404 加跨域报错。
这个几乎每个人都遇到过。浏览器里能看到请求发出,但 Network 里status code是 404 或者提示 CORS error。原因是 manifest.json 的 H5 节点里没有配置开发代理。
正确配置如下:
{ "h5": { "devServer": { "proxy": { "/api": { "target": "https://api.example.com", "changeOrigin": true, "pathRewrite": { "^/api": "" } } } } } }配置好后,请求地址改为/api/goods/detail,HBuilderX 内置的 dev server 就会自动帮你转发到目标域。这个代理只在开发阶段生效,生产构建后还是要靠后端 CORS 配置或 Nginx 反向代理。
案例三:vue2 项目中this.$refs.xxx为 undefined。
在 Vue2 的 uni-app 页面里,this.$refs在小程序端和 H5 端的表现不一致。小程序端部分场景下组件引用不会立即生效,导致undefined。我的解法是尽量少依赖$refs,改用数据驱动;必须用时放在this.$nextTick()回调里:
this.$nextTick(() => { if (this.$refs.someComp) { this.$refs.someComp.doSomething(); } });6.3 提升开发效率的实用技巧
最后分享几个我非常受用的实操技巧,都是直接从日常使用里提炼出来的。
- 善用代码模板(snippet)。在 HBuilderX 里,配置文件模板路径是
数据目录/templates,可以自定义一段<template>+<script>+<style>的组合,建页面时直接插入,省去反复手写。 - 学会使用“运行到终端”配合 uni CLI。HBuilderX 虽然自带图形化操作,但有些特殊命令,比如动态替换环境变量、自定义编译配置,还是用 cli 更灵活。在项目根目录打开终端,执行
npm run dev:h5也能触发编译,效果和界面运行一致。 - 善用
@/路径别名。前面讲过它默认可用,但要注意:在 CSS 文件中引用@/static/logo.png时,小程序端不会帮你解析,这个路径在 CSS 里要写成/static/logo.png,否则小程序端样式里的背景图不生效。 - 多项目同时开发时,关闭不用的项目。HBuilderX 是多进程模型,同一个窗口打开项目太多会拉高内存,还会导致内置浏览器的端口错乱。
- 升级 HBuilderX 前备份
unpackage目录。某些跨版本升级,比如 3.x 到 4.x,可能会改变编译产物结构,做好备份能让你随时回滚。
以我个人的实际体验来说,HBuilderX 最有魅力的地方,恰恰是它把前端开发里最繁琐、最容易出错的“多端编译和调试”环节给吃掉了。你不需要记住微信小程序的setData和 Vue 的响应式数据之间怎么互相转换,只需要按照 Vue 的思维去写业务,剩下的交给工具链。而内置浏览器 debug 的存在,让“写代码—改代码—看到效果”的反馈回路缩短到了几秒钟。这种流畅感是单独使用 VS Code + 多个命令行 tool 很难复现的。如果你目前还在各种编辑器之间反复横跳,不妨花一个下午,用这篇文章里的步骤完整跑一个最小的 uni-app 项目,再来评价它到底适不适合你的日常开发。