Vue、微信小程序、Uniapp 面试题整理
Vue,小程序、uniapp常用的组件有哪些,配套的组件库有哪些?
Vue
常用组件:表单组件、表格组件、弹窗组件、导航菜单、分页组件
组件库:Element UI、Ant Design Vue、Vant、iView
微信小程序
常用组件:视图容器、基础内容、表单组件、导航、媒体组件
组件库:WeUI、Vant Weapp、MinUI、Wux Weapp
Uniapp
常用组件:基础组件(view/text/button)、表单组件、媒体组件、地图
组件库:uni-ui、uView、ColorUI
Vue,小程序、uniapp如何进行路由跳转?
Vue
// 声明式导航
<router-link to="/path"></router-link>
// 编程式导航
this.$router.push('/path')
this.$router.replace('/path')
微信小程序
// 保留当前页面跳转
wx.navigateTo({url: '/page/path'})
// 关闭当前页面跳转
wx.redirectTo({url: '/page/path'})
// 返回
wx.navigateBack()
Uniapp
// 类似小程序API
uni.navigateTo({url: '/pages/path'})
uni.redirectTo({url: '/pages/path'})
// 类似Vue方式
<navigator url="/pages/path"></navigator>
Vue,小程序、uniapp如何发起网络请求?
Vue
// 使用axios
axios.get('/api/data').then(response => {})
axios.post('/api/data', params).then(response => {})
// 或使用fetch
fetch('/api/data').then(response => response.json())
微信小程序
wx.request({
url: 'https://example.com/api',
method: 'GET',
success(res) {},
fail(err) {}
})
Uniapp
uni.request({
url: 'https://example.com/api',
method: 'GET',
success(res) {},
fail(err) {}
})
一、Vue 相关面试题
基础部分
一、Vue 的核心特性是什么?
回答要点:
响应式系统:Vue 使用数据劫持结合发布-订阅模式实现数据响应式,通过 Object.defineProperty(Vue 2)/Proxy(Vue 3) 监听数据变化
组件化开发:单文件组件(SFC)将模板、逻辑和样式封装在一起,提高代码复用性和可维护性
虚拟 DOM:通过高效的 diff 算法最小化 DOM 操作,提升性能
模板语法:声明式渲染,支持插值、指令、过滤器等简化 DOM 操作
过渡动画系统:提供 transition 组件和钩子函数实现元素进入/离开的动画效果
单向数据流:父组件向子组件通过 props 传递数据,子组件通过事件向父组件通信
二、Vue 2 和 Vue 3 的主要区别有哪些?
响应式原理不同(Object.defineProperty vs Proxy)
Composition API 替代 Options API
性能优化(Tree-shaking支持更好)
生命周期变化
更好的TypeScript支持
特性 | Vue 2 | Vue 3 |
---|---|---|
响应式原理 | Object.defineProperty | Proxy |
性能 | 较慢 | 更快(重写虚拟DOM,优化编译等) |
组合API | 选项式API(options API) | 组合式API(composition API) |
Fragment | 不支持 | 支持多根节点组件 |
Teleport | 无 | 新增Teleport组件 |
Suspense | 无 | 新增Suspense组件 |
TypeScript支持 | 一般 | 更好的TS支持 |
打包体积 | 较大 | 更小(更好的tree-shaking) |
三、什么是 MVVM 模式?Vue 是如何实现它的?
MVVM 解释: MVVM(Model-View-ViewModel)是一种软件架构模式,分为三层:
Model:数据模型,代表业务逻辑和数据
View:用户界面,展示数据
ViewModel:连接View和Model的桥梁,负责数据转换和通信
Vue 的实现方式:
数据绑定:通过 v-model 等指令实现双向数据绑定
模板解析:将模板编译成渲染函数
响应式系统:
Vue 2:使用 Object.defineProperty 劫持数据属性的 getter/setter
Vue 3:使用 Proxy 代理整个对象
依赖收集:在 getter 中收集依赖(Watcher),在 setter 中通知更新
虚拟DOM:数据变化时生成新的虚拟DOM,通过diff算法高效更新真实DOM
四、解释 Vue 的生命周期钩子函数及其执行顺序
完整生命周期流程图:
创建阶段:
beforeCreate:实例刚创建,data和methods未初始化
created:实例创建完成,data和methods已初始化,但DOM未生成
挂载阶段:
beforeMount:模板编译完成,但未挂载到页面
mounted:实例挂载到DOM上,可以访问DOM元素
更新阶段:
beforeUpdate:数据变化但DOM未更新
updated:DOM已更新完成
销毁阶段:
beforeDestroy:实例销毁前,仍完全可用
destroyed:实例销毁,所有绑定和监听被移除
五、v-if 和 v-show 的区别是什么?
特性 | v-if | v-show |
---|---|---|
实现方式 | 条件为假时移除DOM节点 | 通过CSS的display属性切换 |
编译 | 惰性的,条件为真才开始编译 | 无论条件如何都会编译 |
性能 | 切换开销大 | 初始渲染开销大 |
适用场景 | 运行时条件很少改变 | 需要频繁切换的场景 |
生命周期 | 触发组件的创建/销毁生命周期 | 只是CSS显示隐藏,不影响生命周期 |
深入解析:
v-if是"真正的"条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建
v-show不管初始条件是什么,元素总是会被渲染,只是简单地基于CSS进行切换
v-if有更高的切换开销,而v-show有更高的初始渲染开销
组件通信
六、Vue 组件间通信的方式有哪些?
父子:props/$emit
子父:$emit/$on
任意组件:Vuex/Pinia
通信场景 | 实现方式 | 代码示例/说明 | 适用场景分析 |
---|---|---|---|
父子通信 | Props + Events | <Child :data="parentData" @update="handleUpdate"/> |
最常用方式,符合单向数据流原则 |
跨级通信 | Provide/Inject | provide('key', value) + const val = inject('key') |
祖先向后代传递数据,适合主题/配置等跨层级共享 |
兄弟通信 | 共同父组件中转 | 父组件作为桥梁传递props和事件 | 简单项目可用,但会增加父组件复杂度 |
任意通信 | 事件总线/Pinia | mitt().emit('event') + mitt().on('event', handler) |
解耦组件关系,但要注意事件清理,避免内存泄漏 |
七、父子组件如何传递数据?
-
父组件向子组件传递数据(Props 向下传递)
步骤 操作说明 数据流向 代码示例 注意事项 1. 父组件准备数据 在父组件中定义要传递的数据 父组件 data → 子组件 data() { return { message: 'Hello' } }
数据应保持响应式 2. 子组件声明接收 子组件通过 props 定义接收属性 父 → 子 props: ['message']
或带类型校验:props: { message: String }
推荐使用对象形式进行类型校验 3. 父组件绑定传递 通过 v-bind 或简写 :
传递单向流动 <Child :message="message" />
遵守单向数据流原则 4. 子组件使用数据 在子组件中像本地数据一样使用 只读 <div>{{ message }}</div>
子组件向父组件传递数据(Events 向上传递)
步骤 | 操作说明 | 数据流向 | 代码示例 | 注意事项 |
---|---|---|---|---|
1. 子组件定义事件 | 在子组件中触发自定义事件 | 子 → 父 | this.$emit('update', newValue) |
事件名推荐 kebab-case |
2. 父组件监听事件 | 父组件通过 v-on 或 @ 监听 |
子组件 → 父方法 | <Child @update="handleUpdate" /> |
可接收事件参数 |
3. 父组件处理数据 | 父组件方法处理数据更新 | 父组件内部更新 | methods: { handleUpdate(val) { this.data = val } } |
保持数据修改权在父级 |
4. 可选双向绑定 | 使用 v-model 语法糖 | 双向同步 | <Child v-model="parentData" /> |
八、非父子组件如何通信?
Pinia/Vuex:适合管理全局状态如用户信息,我们后台系统用Pinia共享权限数据;
事件总线:用
mitt
库实现通知型通信,比如购物车更新事件;Provide/Inject:跨层级传递UI主题配置;
本地存储:实现不同标签页间的数据同步;
组合式函数:封装可复用的业务逻辑状态。
二、微信小程序面试题
基础部分
一、微信小程序的文件结构是怎样的?
app.json:全局配置
app.js:入口文件
app.wxss:全局样式
pages:页面目录
utils:工具函数
文件类型 | 必选 | 作用 | 示例文件 |
---|---|---|---|
app.json | 是 | 全局配置(页面路径、窗口样式、网络超时等) | json { "pages": ["pages/index/index"], "window": { "navigationBarTitleText": "Demo" } } |
app.js | 是 | 小程序入口文件(注册全局生命周期和全局变量) | js App({ onLaunch() {} }) |
app.wxss | 否 | 全局样式(类似CSS) | css page { background: #f00; } |
页面文件 | |||
└─.js | 是 | 页面逻辑(数据、生命周期、函数) | js Page({ data: { text: "Hello" } }) |
└─.wxml | 是 | 页面结构(类似HTML) | xml <view>{{text}}</view> |
└─.wxss | 否 | 页面样式 | css view { color: blue; } |
└─.json | 否 | 页面单独配置(覆盖app.json的window设置) | json { "navigationBarTitleText": "首页" } |
其他文件 | |||
└─components/ | 否 | 自定义组件目录(包含类似页面的4个文件) | js Component({ properties: { propA: String } }) |
二、小程序的生命周期函数有哪些?
应用级别(App生命周期)
函数 | 触发时机 | 示例代码 |
---|---|---|
onLaunch |
小程序初始化完成时(全局只触发一次) | js App({ onLaunch(options) {} }) |
onShow |
小程序启动或从后台进入前台 | js onShow() { console.log('显示') } |
onHide |
小程序从前台进入后台 |
页面级别(Page生命周期)
函数 | 触发时机 | 执行顺序 |
---|---|---|
onLoad |
页面加载时(可获取路由参数) | 1 |
onShow |
页面显示/切入前台时 | 2 |
onReady |
页面初次渲染完成时 | 3 |
onHide |
页面隐藏/切入后台时 | |
onUnload |
页面卸载时(跳转或关闭) |
三、小程序页面间如何传递数据?
1. URL参数传递(最常用)
适用场景:传递简单参数(如ID、类型标识)
javascript
// 跳转时传参
wx.navigateTo({url: '/page?id=1'})
// 接收参数
Page({
onLoad(options) {
const id = options.id
}
})
五、小程序的双向绑定和 Vue 有什么不同?
Vue:v-model直接双向绑定
小程序:需要绑定事件手动setData
1. 实现原理对比
维度 | 小程序 | Vue | 技术解析 |
---|---|---|---|
底层机制 | 基于setData 的数据比对更新 |
基于Object.defineProperty /Proxy 的响应式依赖追踪 |
小程序需要显式调用setData 触发渲染,Vue自动追踪依赖 |
数据流 | 单向数据流(需手动同步视图与数据) | 双向绑定(v-model 语法糖自动同步) |
Vue通过v-model="data" 等价于:value="data" @input="data=$event" |
更新粒度 | 全量diff (需自行优化) |
精准到字段的颗粒度更新 | 小程序中setData({a:1}) 会导致整个data对象被对比,Vue只更新依赖a的组件 |
进阶部分
七、如何优化小程序的性能?
减少setData调用频率和数据量
使用分包加载
图片压缩
合理使用onPageScroll
八、小程序如何实现自定义组件?
创建组件目录
配置component: true
使用properties定义属性
父组件通过属性传递数据
三、Uniapp 面试题
基础部分
一、Uniapp 是什么?它有什么优势?
"Uniapp 是一款基于 Vue.js 的跨平台开发框架
跨平台开发效率高(一次开发,多端发布)
基于Vue.js技术栈,学习成本低
丰富的插件市场和组件库
官方文档完善,中文支持好
社区活跃,问题容易解决
二、Uniapp 如何实现多端兼容?
运行时根据不同平台编译为对应代码
条件编译处理平台差异
统一的API调用方式
三、Uniapp 的生命周期有哪些?
页面生命周期:
onLoad - 页面加载
onShow - 页面显示
onReady - 页面就绪
onHide - 页面隐藏
onUnload - 页面卸载
应用生命周期:
onLaunch - 应用初始化
onShow - 应用切换到前台
onHide - 应用切换到后台
onError - 脚本错误监听
组件生命周期:
beforeCreate → created → beforeMount → mounted → beforeUpdate → updated → beforeDestroy → destroyed
进阶部分
六、Uniapp 如何实现条件编译?
// #ifdef H5
console.log('只在H5平台执行')
// #endif
// #ifdef MP-WEIXIN
console.log('只在微信小程序执行')
// #endif
四、跨框架问题
一、Vue、微信小程序和 Uniapp 在数据绑定方面的异同
Vue:双向绑定,v-model
小程序:单向绑定,需手动setData
Uniapp:类似Vue,但部分平台有限制
二、如何将 Vue 项目迁移到 Uniapp?
调整目录结构
替换特定API
处理平台差异
使用条件编译
三、移动端开发中常见的性能优化手段有哪些?
图片懒加载
减少DOM节点
节流防抖
合理使用缓存
避免频繁setData
五、项目经验相关
一、你做过的最复杂的 Vue/小程序/Uniapp 项目是什么?遇到了什么挑战?
跨平台兼容性问题
性能优化(如长列表渲染)
与原生功能交互
多端UI一致性
二、你在性能优化方面做过哪些工作?
使用虚拟列表优化长列表
图片压缩和懒加载
减少不必要的数据响应
合理使用缓存策略
三、你是如何进行移动端测试的?
真机测试
多平台兼容性测试
性能分析工具
用户行为测试