Vue、微信小程序、Uniapp 面试题整理最新整合版
目录
Vue,小程序、uniapp常用的组件有哪些,配套的组件库有哪些?
Vue,小程序、uniapp如何进行路由跳转?
Vue,小程序、uniapp如何发起网络请求?
一、Vue 相关面试题
基础部分
1、Vue 的核心特性是什么?
2、Vue 2 和 Vue 3 的主要区别有哪些?
3、什么是 MVVM 模式?Vue 是如何实现它的?
4、解释 Vue 的生命周期钩子函数及其执行顺序?
5、v-if 和 v-show 的区别是什么?
v-if 和 v-show 对比表
组件通信
1、Vue 组件间通信的方式有哪些?
2、父子组件如何传递数据?
3、非父子组件如何通信?
4、Vuex |Pinia的核心概念是什么?
5、什么时候应该使用 Vuex|PInia?
二、微信小程序面试题
基础部分
1、微信小程序的文件结构是怎样的?
2、小程序的生命周期函数有哪些?
3、小程序页面间如何传递数据?
4、小程序的 WXSS 和 CSS 有什么区别?
5、小程序的双向绑定和 Vue 有什么不同?
1. 数据流控制逻辑
2. 语法设计差异
3. 底层实现原理
进阶部分
1、小程序的运行机制是怎样的?
2、如何优化小程序的性能?
3、小程序如何实现自定义组件?
4、小程序的登录流程是怎样的?
实战问题
1、小程序如何实现下拉刷新和上拉加载更多?
2、如何处理小程序的兼容性问题?
3、小程序如何实现数据缓存?
4、小程序如何调用微信原生 API?
5、小程序如何实现分享功能?
三、Uniapp 面试题
基础部分
1、Uniapp 是什么?它有什么优势?
2、Uniapp 如何实现多端兼容?
3、Uniapp 的生命周期有哪些?
4、Uniapp 如何调用原生功能?
5、Uniapp 的页面路由与微信小程序有什么不同?
进阶部分
1、Uniapp 如何实现条件编译?
2、Uniapp 如何优化多端应用的性能?
3、Uniapp 如何实现原生插件开发?
4、Uniapp 如何处理多端样式兼容问题?
5、Uniapp 如何实现热更新?
实战问题
1、Uniapp 如何实现微信登录?
2、Uniapp 如何实现支付功能?
3、Uniapp 如何实现消息推送?
4、Uniapp 如何适配不同屏幕尺寸?
5、Uniapp 如何打包发布到不同平台?
四、跨框架问题
1、Vue、微信小程序和 Uniapp 在数据绑定方面的异同
2、如何将 Vue 项目迁移到 Uniapp?
3、Vue 组件和小程序/Uniapp 组件的区别
4、如何解决跨平台开发中的样式兼容问题?
5、移动端开发中常见的性能优化手段有哪些?
6、如何实现一套代码适配多个平台?
7、H5、小程序和 App 开发的主要区别是什么?
8、如何调试多端应用?
9、你如何处理不同平台的 API 差异?
五、项目经验相关
1、你做过的最复杂的 Vue/小程序/Uniapp 项目是什么?遇到了什么挑战?
2、你是如何解决跨平台兼容性问题的?
3、你在性能优化方面做过哪些工作?
4、你如何处理移动端的用户体验问题?
5、你是如何进行移动端测试的?
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 | - <router-view> - <transition> - <keep-alive> - <slot> | 1. Element UI (桌面端) 2. Ant Design Vue (桌面端) 3. Vant (移动端) 4. Naive UI (现代 UI) 5. Quasar (全平台) | Vue 的组件库生态丰富,根据项目类型(桌面/移动)选择不同的库。 |
微信小程序 | - <view> - <text> - <button> - <scroll-view> - <swiper> | 1. WeUI (官方风格) 2. Vant Weapp (移动端) 3. Lin UI 4. Wux Weapp 5. MinUI | 小程序原生组件以基础功能为主,第三方库增强交互和样式。 |
Uniapp | - <view> - <uni-list> - <uni-swiper> - <uni-icons> | 1. Uni UI (官方扩展组件) 2. uView UI (高集成度) 3. ColorUI (视觉风格) 4. FirstUI 5. Vant Uni (适配版) | Uniapp 兼容 Vue 和小程序语法,组件库需支持多端(H5/小程序/App)。 |
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 中,我们使用 vue-router
插件提供的 this.$router.push()
或 <router-link>
标签来进行路由跳转;而在微信小程序中,则是通过 wx.navigateTo()
等 API 实现页面间的导航;UniApp 结合了两者的优势,既可以通过类似 Vue 的 $router.push()
方法,也可以使用 uni.navigateTo()
等跨平台 API 来完成路由跳转,同时还支持条件编译来处理平台特定的跳转需求。
一、Vue 中的路由跳转
1. 使用 Vue Router
-
安装 Vue Router:首先需要安装
vue-router
,并通过Vue.use(VueRouter)
来注册插件。 -
定义路由:在路由配置文件中定义路径与组件的映射关系。
-
编程式导航
-
使用
this.$router.push(location)
方法进行跳转,其中location
可以是一个字符串路径或一个描述目标位置的对象。 -
示例(文字描述):
调用
this.$router.push('/about')
进行跳转到/about
页面;或者使用对象形式this.$router.push({ path: '/about', query: { id: 123 }})
,携带参数跳转。 -
this.$router.replace(location)
类似于push
,但它不会留下历史记录。 -
this.$router.go(n)
按照当前历史记录前进或后退 n 步。
-
-
声明式导航
-
在模板中使用
<router-link>
标签来进行导航。 -
示例(文字描述):
使用
<router-link to="/about">About</router-link>
创建一个链接,点击时会跳转到/about
页面。
-
二、微信小程序中的路由跳转
1. 使用 wx API
-
页面跳转
-
使用
wx.navigateTo()
方法跳转至应用内某个页面,并保留当前页面。 -
示例(文字描述):
调用
wx.navigateTo({ url: '/pages/detail/detail?id=1' })
跳转到detail
页面并传递参数id=1
。 -
使用
wx.redirectTo()
方法关闭当前页面,跳转到应用内的某个页面。 -
使用
wx.switchTab()
方法跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。 -
使用
wx.navigateBack()
方法返回上一页或多页。
-
2. 页面栈管理
-
微信小程序维护了一个页面栈,
wx.navigateTo()
会将新页面压入栈顶,而wx.navigateBack()
则是从栈顶弹出页面。 -
可以通过
getCurrentPages()
获取当前页面栈的信息,了解当前处于哪个页面。
三、UniApp 中的路由跳转
1. 兼容 Vue 和小程序的路由
-
基于 Vue Router 的方式
-
UniApp 支持 Vue Router 的大部分特性,可以像在 Vue 项目中一样使用
this.$router.push()
等方法进行路由跳转。 -
示例(文字描述):
调用
this.$router.push({ path: '/pages/detail/detail', query: { id: 123 }})
实现带参数的页面跳转。
-
-
基于 uni API 的方式
-
UniApp 提供了
uni.navigateTo()
、uni.redirectTo()
、uni.switchTab()
、uni.navigateBack()
等 API 来进行跨平台的页面跳转,这些 API 兼容微信小程序和其他平台。 -
示例(文字描述):
使用
uni.navigateTo({ url: '/pages/detail/detail?id=123' })
进行页面跳转,适用于多平台场景。
-
-
条件编译支持
-
对于某些特定平台独有的跳转逻辑,可以使用条件编译来处理。
- 示例(文字描述):
#ifdef MP-WEIXIN// 微信小程序特有的跳转逻辑wx.navigateTo({ url: '/pages/wechatDetail/wechatDetail' }); #endif
-
Vue,小程序、uniapp如何发起网络请求?
Vue
方法 | 幂等性 | 安全性 | 请求体 | 缓存 | 主要用途 |
---|---|---|---|---|---|
GET | 是 | 是 | 无 | 可 | 获取数据 |
POST | 否 | 否 | 有 | 不可 | 创建数据 |
PUT | 是 | 否 | 有 | 不可 | 更新全部 |
DELETE | 是 | 否 | 通常无 | 不可 | 删除资源 |
// 使用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 中通常使用 axios
或 fetch
发起网络请求,在组件的生命周期中调用,并封装统一的请求工具;在微信小程序中主要使用 wx.request
方法,并需配置域名白名单;而在 UniApp 中,使用 uni.request
方法,它在不同平台下自动适配,适合跨平台开发。三者都可以通过封装统一请求工具来处理错误、加载状态、拦截器等功能,提升开发效率和维护性。
平台 | 请求方法 | 是否支持拦截器 | 是否跨平台 | 常用封装方式 |
---|---|---|---|---|
Vue | axios / fetch | ✅ 是 | ❌ 否 | 封装 http.js |
小程序 | wx.request | ❌ 否 | ❌ 否 | 封装 utils.js |
UniApp | uni.request | ✅ 可封装实现 | ✅ 是 | 封装 api.js 或 request.js |
一、Vue 相关面试题
基础部分
1、Vue 的核心特性是什么?
- 数据驱动(响应式系统):Vue 的核心机制,通过数据变化自动更新视图,无需直接操作 DOM
- 组件化开发:将UI拆分为独立可复用的组件,形成树状结构
- 指令系统:特殊的HTML属性,带有
v-
前缀,用于响应式地操作DOM - 虚拟DOM:用JavaScript对象模拟真实DOM结构,通过diff算法高效更新视图
- 模板语法:基于HTML的声明式模板,可以插入数据绑定和指令
核心特性 | 描述 | 示例/说明 |
---|---|---|
响应式数据绑定 | 数据变化时视图自动更新,基于 Proxy (Vue 3)或 Object.defineProperty (Vue 2)。 | v-model 实现表单双向绑定。 |
组件化开发 | 将 UI 拆分为独立、可复用的组件(.vue 文件)。 | 单文件组件包含 <template> 、<script> 、<style> 。 |
声明式模板语法 | 通过指令(如 v-if 、v-for )声明式描述视图逻辑。 | <div v-if="show">Hello</div> 。 |
虚拟 DOM | 用 JS 对象模拟真实 DOM,通过 Diff 算法高效更新视图。 | 减少直接操作 DOM,提升性能。 |
指令系统 | v- 前缀的特殊属性,用于绑定数据或操作 DOM。 | v-bind:href="url" 、v-on:click="handleClick" 。 |
生命周期钩子 | 在组件不同阶段(如创建、挂载、更新)触发逻辑。 | created() 、mounted() 用于初始化数据或访问 DOM。 |
状态管理(Vuex/Pinia) | 集中管理跨组件共享状态,提供可预测的数据流。 | Vuex 的 state 、mutations ;Pinia 的 stores 。 |
路由管理(Vue Router) | 实现 SPA 的无刷新页面切换和嵌套路由。 | router-link 导航,router-view 占位。 |
组合式 API(Vue 3) | 通过 setup() 和响应式 API(ref 、reactive )组织逻辑,提升复用性。 | const count = ref(0) ;watch(count, () => {...}) 。 |
渐进式框架 | 可逐步集成功能,从核心库扩展到路由、状态管理等。 | 仅引入 vue.js 处理简单交互,或搭配全家桶构建复杂应用。 |
2、Vue 2 和 Vue 3 的主要区别有哪些?
- 响应式原理不同(Object.defineProperty vs Proxy):
- Composition API 替代 Options API
- 性能优化(Tree-shaking支持更好)
- 生命周期变化
- 更好的TypeScript支持
(1)响应式系统的实现
特性 | Vue 2 | Vue 3 |
---|---|---|
响应式原理 | 使用 Object.defineProperty 实现数据劫持 | 使用 Proxy (ES6)实现,更强大、性能更好 |
数组响应式 | 特殊处理(重写数组方法) | 原生支持数组的响应式更新 |
响应式对象创建 | Vue.set() 或 this.$set() | 不再需要,Proxy 自动追踪 |
(2) 性能优化
特性 | Vue 2 | Vue 3 |
---|---|---|
渲染性能 | 相对较慢 | 更快,通过重写虚拟 DOM 和编译优化提升 |
包体积 | 较大 | 更小,通过 Tree-shaking 优化,减少冗余代码 |
编译优化 | 运行时编译较多 | 编译器增强,静态提升、Patch 标记等优化 |
(3)Composition API(组合式 API)
特性 | Vue 2 | Vue 3 |
---|---|---|
API 风格 | Options API(选项式)为主 | 支持 Composition API(组合式),更灵活组织逻辑 |
逻辑复用 | 依赖 Mixins,存在命名冲突问题 | 使用 setup() 和自定义 Hook 函数,逻辑更清晰 |
(4)TypeScript 支持
特性 | Vue 2 | Vue 3 |
---|---|---|
TypeScript 支持 | 支持但不够原生 | 完全支持 TypeScript,代码结构更清晰、类型更安全 |
(5)生命周期钩子
特性 | Vue 2 | Vue 3 |
---|---|---|
生命周期名称 | beforeCreate , created , beforeMount , mounted 等 | 保持兼容,但在 Composition API 中使用 onBeforeMount , onMounted 等函数形式 |
(6)模板语法与组件
特性 | Vue 2 | Vue 3 |
---|---|---|
多根组件 | 不支持(必须包裹在一个根元素内)<value> | 支持 Fragment(可有多个根节点) |
自定义指令 | 指令钩子函数较少 | 指令钩子更丰富,与组件生命周期更一致 |
Teleport | 不支持 | 新增 <Teleport> 组件,实现元素渲染到任意位置 |
Suspense | 不支持 | 新增 <Suspense> 组件,支持异步加载组件 |
3、什么是 MVVM 模式?Vue 是如何实现它的?
MVVM(Model-View-ViewModel)是一种软件架构设计模式,主要用于简化用户界面的开发。它将应用程序分为三个部分:
- Model:代表应用的数据和业务逻辑,负责处理数据的获取、存储等操作。
- View:定义了用户界面的结构和布局,显示数据并接收用户的交互。
- ViewModel:作为桥梁连接 Model 和 View,负责处理视图的逻辑,同时提供数据绑定到视图的方法,并能响应视图中的用户输入。
MVVM 的工作原理
在 MVVM 模式中,ViewModel 监听 Model 中的数据变化,并更新到 View;同时,它也监听 View 中发生的事件(如用户输入),并将这些更改反映回 Model。这种双向数据绑定机制使得开发者不需要手动编写代码来同步 View 和 Model 之间的状态,从而提高了开发效率。
Vue 如何实现 MVVM
Vue.js 是一个实现了 MVVM 设计模式的前端框架,其核心就是通过声明式的语法来实现数据与视图之间的双向绑定。以下是 Vue 实现 MVVM 的几个关键点:
-
数据绑定:Vue 使用声明式的数据绑定机制,允许你轻松地将数据模型绑定到 DOM(文档对象模型)上。当数据模型发生变化时,Vue 自动更新相应的视图,反之亦然。
-
模板引擎:Vue 使用基于HTML的模板语法,允许开发者声明式地将DOM绑定到底层Vue实例的数据。
-
计算属性与侦听器:Vue 提供了计算属性(computed properties)和侦听器(watchers)来处理复杂的逻辑或依赖关系。计算属性可以基于其他数据进行计算,并且只有在其依赖的数据发生改变时才会重新计算。侦听器则用于执行异步操作或开销较大的操作。
-
组件系统:Vue 的组件系统允许你构建大型应用程序,并将其拆分成可复用的独立组件。每个组件都有自己的视图和数据逻辑,这与 MVVM 中 ViewModel 的概念相吻合。
-
虚拟DOM:Vue 使用虚拟DOM技术来提高性能,通过比较前后两次虚拟DOM树的差异,仅将变化的部分应用到实际DOM上,减少了不必要的DOM操作。
4、解释 Vue 的生命周期钩子函数及其执行顺序?
beforeCreate → created → beforeMount → mounted → beforeUpdate → updated →
beforeDestroy → destroyed
阶段 | 钩子函数 | 触发时机 | 用途 | 注意事项 |
---|---|---|---|---|
创建阶段 | beforeCreate | 实例初始化后,数据观测(data )和事件配置(events )之前。 | 初始化非响应式变量(如插件配置)。 | 无法访问 data 和 methods 。 |
created | 实例创建完成,数据观测和事件配置已完成,但 DOM 未挂载。 | 发起异步请求、初始化数据。 | 可访问 data ,但 $el 为 undefined 。 | |
挂载阶段 | beforeMount | 模板编译完成,但尚未将虚拟 DOM 渲染为真实 DOM。 | 极少使用,通常用于服务端渲染(SSR)。 | $el 存在但内容为空。 |
mounted | 实例挂载到 DOM 后,真实 DOM 已生成。 | 操作 DOM、集成第三方库(如地图、图表)。 | 子组件的 mounted 先于父组件执行。 | |
更新阶段 | beforeUpdate | 数据变化后,虚拟 DOM 重新渲染和打补丁之前。 | 获取更新前的 DOM 状态(如保存滚动位置)。 | 避免在此修改数据,可能循环触发更新。 |
updated | 虚拟 DOM 重新渲染并应用补丁后。 | 数据变化后操作 DOM(如调整样式)。 | 避免直接修改数据,可能导致无限循环。 | |
销毁阶段 | beforeDestroy | 实例销毁前,此时实例仍完全可用。 | 清理定时器、解绑事件、取消未完成的异步任务。 | Vue 3 中更名为 beforeUnmount 。 |
destroyed | 实例销毁后,所有绑定和监听被移除,子实例也被销毁。 | 善后工作(如释放非 Vue 管理的资源)。 | Vue 3 中更名为 unmounted 。 |
父子组件生命周期执行顺序对比
场景 | 执行顺序 |
---|---|
加载时 | 父 beforeCreate → 父 created → 父 beforeMount → 子 beforeCreate → 子 created → 子 beforeMount → 子 mounted → 父 mounted |
更新时 | 父 beforeUpdate → 子 beforeUpdate → 子 updated → 父 updated |
销毁时 | 父 beforeDestroy → 子 beforeDestroy → 子 destroyed → 父 destroye |
5、v-if 和 v-show 的区别是什么?
- v-if:条件渲染,不满足时元素不存在于DOM
- v-show:条件显示,通过CSS控制,元素始终在DOM中
v-if
和 v-show
对比表
对比项 | v-if | v-show |
---|---|---|
渲染机制 | 条件性渲染:动态添加/移除 DOM 节点 | 显示切换:通过 CSS display: none 控制显示/隐藏 |
初始渲染 | 初始为 false 时,不渲染 DOM | 无论条件如何,始终渲染 DOM,仅切换显示状态 |
切换开销 | 高(涉及 DOM 增删和子组件生命周期) | 低(仅修改 CSS 属性) |
适用场景 | 运行时条件很少改变(如权限控制) | 需要频繁切换显示状态(如选项卡) |
生命周期 | 切换时会触发组件的 created /destroyed 钩子 | 组件始终保持挂载,仅触发 mounted 一次 |
性能影响 | 减少初始渲染负载,但频繁切换性能差 | 初始渲染负载高,但切换性能优 |
组件通信
1、Vue 组件间通信的方式有哪些?
组件通信方式:
父子:props/$emit
子父:$emit/$on
任意组件:Vuex/Pinia
1. 父子通信:props
/ $emit
这是最基础、最常用的组件通信方式。
-
props
(父传子):- 作用:父组件向子组件传递数据。
- 原理:父组件在使用子组件时,通过属性(attribute)的方式将数据传递给子组件。子组件通过
props
选项显式地声明它期望接收的数据。 - 特点:单向数据流。数据从父组件流向子组件。子组件不应该直接修改
props
的值(Vue 会警告),如果需要修改,应该通过事件通知父组件。
-
$emit
(子传父): -
- 作用:子组件向父组件发送事件,通常用于通知父组件状态变化或请求操作。
- 原理:子组件通过调用
this.$emit('事件名', 数据)
触发一个自定义事件,并可以携带数据。父组件在使用子组件的标签上,通过v-on
(或@
) 监听这个事件,并定义处理函数。 - 特点:这是子组件通知父组件的主要方式。父组件在事件处理函数中可以修改自己的数据,这些数据再通过
props
传递回子组件(形成闭环)。
2、 任意组件通信:Vuex / Pinia
当组件层级较深或多个不相关的组件需要共享状态时,使用状态管理库。
-
Vuex:
- Vue 2 官方的状态管理库,Vue 3 也兼容,但现在更推荐 Pinia。
- 核心概念:
State
(单一状态树),Getters
(计算属性),Mutations
(同步修改状态),Actions
(异步操作,提交 Mutations)。 - 所有组件都可以通过
mapState
,mapGetters
辅助函数或直接访问$store.state
来读取状态;通过mapMutations
,mapActions
或this.$store.commit/dispatch
来修改状态。
-
Pinia:
- Vue 3 的官方推荐状态管理库,也是 Vue 2 的官方推荐(通过插件)。
- 优势:更简洁的 API(基于
store
模块,无 Mutations,Actions 可同步可异步)、更好的 TypeScript 支持、模块化设计(天然分模块)、支持组合式 API (setup
)。 - 核心:定义
store
(使用defineStore
),包含state
,getters
,actions
。组件中通过useXXXStore()
获取 store 实例来访问和修改状态。
-
工作流程:
- 创建一个全局的 Store (Vuex Store 或 Pinia Store)。
- 需要共享的数据放在 Store 的
state
中。 - 任何组件都可以读取这个
state
。 - 当组件需要修改共享状态时,必须通过调用 Store 提供的
actions
(或 Vuex 的mutations
) 来进行,保证状态变更的可追踪性。 - 状态变更后,所有依赖该状态的组件会自动更新。
-
适用场景:用户登录状态、购物车信息、全局配置、多级嵌套组件间复杂的数据流等。
2、父子组件如何传递数据?
(1)父组件向子组件传递数据
父→子:props
父组件通过 props
向子组件传递数据。
子组件在定义时声明它需要接收哪些外部数据(即 props),包括数据的名称、类型、默认值等。
父组件在使用子组件时,通过绑定属性的方式,将数据传入子组件内部。
这种方式适用于传递静态数据、动态数据、函数、对象、数组等。
(2)子组件向父组件传递数据
子→父:$emit事件
子组件通过 触发自定义事件($emit
) 向父组件传递信息。
当子组件内部发生某些行为(如点击、输入、状态变化)时,可以使用 $emit
方法触发一个事件,并携带数据。
父组件监听该事件,并在其模板中通过事件绑定语法指定处理函数,从而接收到子组件传来的数据。
3、非父子组件如何通信?
Vuex / Pinia 状态管理库
-
使用 Vuex(Vue 2 和 Vue 3 都支持)或 Pinia(Vue 3 推荐的状态管理库),将共享数据集中存放在一个全局的“store”中。
-
所有组件都可以从 store 中读取数据或提交更改,从而实现跨组件通信。
-
适用于中大型项目,提供统一的状态管理机制,便于维护和调试。
4、Vuex |Pinia的核心概念是什么?(了解)
Vuex 和 Pinia 是 Vue.js 应用中用于状态管理的库,它们帮助开发者集中管理和维护应用的状态。以下是它们的核心概念说明:
Vuex 核心概念
-
State(状态):代表存储在 store 中的数据,是驱动你的应用的数据源。
-
Getter:类似于 Vue 组件中的计算属性,用于从 state 中派生出一些状态,这些状态可以根据其他状态计算得出。
-
Mutation(变更):唯一可以改变 store 中状态的方法,必须是同步函数。通过提交 mutation 来修改状态。
-
Action:类似 Mutation,但主要用于处理异步操作,并且可以包含任意异步操作。Action 提交的是 Mutations 而不是直接变更状态。
-
Module(模块):为了便于管理大型项目中的状态,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter。
Pinia 核心概念
Pinia 是一个更现代的状态管理库,旨在解决 Vuex 中的一些限制和痛点,其核心概念如下:
-
Store(存储):Pinia 的核心概念之一,是一个包含了状态、getters 和 actions 的容器。与 Vuex 不同,Pinia 没有强制性的层级结构,所有 Store 都是平等的。
-
State:同样代表了应用的状态,但定义更加灵活,可以直接在 Store 内部定义为响应式对象。
-
Getters:用于从 State 中派生出一些值,功能上类似于 Vuex 的 Getters,但是使用起来更加直观和灵活。
-
Actions:用于执行业务逻辑或异步操作,可以访问并修改 State,也可以调用其他的 Actions 或 Getters。
-
插件支持:Pinia 支持插件扩展,可以通过插件来增强 Store 的功能,如添加全局状态、集成第三方服务等。
-
无模块嵌套限制:Pinia 采用扁平化的 Store 结构,避免了 Vuex 中的模块嵌套问题,使得跨 Store 的状态共享变得简单。
5、什么时候应该使用 Vuex|PInia?(了解)
使用 Vuex 或 Pinia 的场景
-
全局状态管理:当你的应用需要在多个组件间共享状态(如用户登录状态、购物车信息等),而这些状态不仅限于父子组件关系时,使用 Vuex 或 Pinia 可以帮助你集中管理和维护这些状态。
-
复杂的状态逻辑:如果你的应用包含复杂的业务逻辑或状态变化,比如需要处理异步操作(如 API 调用)、条件性地更新状态或基于其他状态计算出新的状态,那么 Vuex 和 Pinia 提供的结构化方式可以帮助你更好地组织代码。
-
大型项目或团队协作:对于较大的项目或者多人协作的团队,使用 Vuex 或 Pinia 可以提供一个明确的状态管理方案,有助于保持代码的一致性和可维护性。这可以减少因状态管理不当导致的错误和冲突。
-
状态持久化需求:如果你的应用需要将某些状态持久化(例如保存用户的偏好设置),Vuex 和 Pinia 都可以通过插件或其他方法支持这一需求。
选择 Vuex 还是 Pinia?
-
Vuex:
- 如果是从 Vue 2 过渡到 Vue 3,且对 Vuex 模式非常熟悉,可以选择继续使用 Vuex。
- Vuex 有更严格的架构约束(如 Mutations 必须是同步的),这对于一些开发者来说可能是优势,因为它强制了更好的状态管理实践。
-
Pinia:
- 更加灵活和直观,减少了样板代码,使得开发体验更加流畅。
- 对 TypeScript 支持更好,提供了类型推断和更好的类型安全。
- 适合新项目或是想要简化状态管理流程的团队,尤其是在 Vue 3 环境下。
总结
- 小型应用:如果只是一个简单的单页应用(SPA),可能不需要引入 Vuex 或 Pinia,直接通过组件间的 Props 和 Events 即可满足需求。
- 中大型应用:随着应用的增长,尤其是当你发现状态管理变得越来越复杂时,考虑引入 Vuex 或 Pinia 来管理全局状态会是一个不错的选择。
- Vue 3 项目:推荐使用 Pinia,因其设计更加现代化,API 更加友好,尤其适合新的 Vue 3 项目。
二、微信小程序面试题
基础部分
1、微信小程序的文件结构是怎样的?
文件/目录 | 作用 | 关键特性 | 示例/备注 |
---|---|---|---|
app.json | 全局配置 | 定义页面路径、窗口样式、tabBar 、网络超时等 | 必须配置 pages 字段,第一项为启动页。 |
app.js | 入口逻辑文件 | 监听小程序生命周期、定义全局数据(globalData ) | 通过 getApp() 获取实例。 |
app.wxss | 全局样式 | 所有页面共享样式(可被页面样式覆盖) | 使用 rpx 单位适配屏幕。 |
pages/ | 存放所有页面 | 每个页面包含 .js (逻辑)、.json (配置)、.wxml (结构)、.wxss (样式) | 页面配置(.json )会覆盖 app.json 中的 window 设置。 |
utils/ | 公共工具函数 | 封装复用逻辑(如请求、工具类函数) | 需手动引入到页面或组件中使用。 |
2、小程序的生命周期函数有哪些?
- App生命周期:onLaunch, onShow, onHide
- Page生命周期:onLoad, onShow, onReady, onHide, onUnload
应用生命周期函数
这些函数定义在 app.js
文件中,用于监听整个小程序的生命周期。
-
onLaunch:当小程序初始化完成时触发(全局只触发一次)。
-
onShow:当小程序启动,或从后台进入前台显示时触发。
-
onHide:当小程序从前台进入后台时触发。
-
onError:当小程序发生脚本错误或者 API 调用失败时触发,参数为错误信息。
页面生命周期函数
这些函数定义在每个页面的 .js
文件中,用于监听页面的生命周期。
-
onLoad:监听页面加载,其参数为页面跳转过来的参数。
-
onShow:监听页面显示。每次页面出现时都会触发,包括从后台切到前台。
-
onReady:监听页面初次渲染完成。注意,此事件仅在页面首次显示时触发一次。
-
onHide:监听页面隐藏。当用户导航到其他页面或小程序退到后台时触发。
-
onUnload:监听页面卸载。当页面被关闭或替换时触发,比如通过返回键回到前一个页面时当前页面会被卸载。
-
onPullDownRefresh:监听用户下拉动作。需要在
app.json
或对应的页面json
配置"enablePullDownRefresh": true
来启用。 -
onReachBottom:页面上拉触底事件的处理函数。可以用来加载更多数据。
-
onShareAppMessage:用户点击右上角菜单的“转发”按钮时触发。可以通过此函数自定义转发内容。
-
onPageScroll:监听页面滚动。参数为页面滚动的距离信息。
-
onResize:监听窗口尺寸变化。可用于响应屏幕旋转等导致的布局调整。
-
onTabItemTap:点击 tab 时触发。参数包含被点击的 tab 信息。
3、小程序页面间如何传递数据?
// 跳转时传参
wx.navigateTo({url: '/page?id=1'})
// 接收参数
Page({
onLoad(options) {
const id = options.id
}
})
1. 通过页面跳转时传递参数
在页面跳转时,可以通过 wx.navigateTo
、wx.redirectTo
或 wx.reLaunch
等方法携带参数,将数据传递给目标页面。这些参数会作为目标页面 onLoad
生命周期函数的参数传入。这种方式适用于简单数据(如字符串、数字)的传递。
2. 通过全局变量(App 全局对象)
可以在 app.js
中定义全局变量,用于存储需要跨页面共享的数据。各个页面都可以访问和修改这些变量,从而实现页面间的数据共享。这种方式适合少量共享数据的场景,但需要注意数据同步和管理,避免混乱。
4、小程序的 WXSS 和 CSS 有什么区别?(了解)
特性/对比项 | WXSS(微信小程序样式) | CSS(网页样式) |
---|---|---|
全称 | WeiXin Style Sheets | Cascading Style Sheets |
运行环境 | 微信小程序环境(小程序框架内) | 浏览器环境(HTML 页面) |
尺寸单位 | 支持 rpx (响应式像素),适配不同设备屏幕宽度 | 使用 px 、em 、rem 、vw 、vh 等标准单位 |
样式导入 | 支持 @import 导入其他 .wxss 文件,路径为相对路径 | 支持 @import 导入其他 CSS 文件 |
选择器支持 | 支持部分 CSS 选择器,部分高级选择器不支持(如 > , + , ~ 等) | 支持完整的 CSS 选择器(包括伪类、伪元素等) |
全局与局部样式 | app.wxss 为全局样式,各页面 .wxss 为局部样式,优先级更高 | 通常通过外部 CSS 文件引入,可通过类名或 ID 控制样式作用域 |
动态样式绑定 | 支持通过 {{ }} 数据绑定动态设置 style 或 class | 一般通过 JavaScript 操作 DOM 来动态修改样式 |
伪类和伪元素支持 | 支持有限,如 ::after 、::before 可能不完全支持 | 完整支持伪类(如 :hover , :nth-child )和伪元素(如 ::before , ::after )等 |
兼容性处理 | 不需要考虑浏览器兼容性问题,统一在微信小程序环境下运行 | 需要考虑浏览器兼容性(如不同浏览器对 CSS 的支持差异) |
样式作用域 | 天然模块化,页面样式默认只作用于当前页面 | 需要通过命名空间或 CSS Modules 等方式避免样式冲突 |
开发体验 | 更适合小程序开发,与 WXML、JS 配合紧密,开发效率高 | 更灵活,但需配合 HTML 和 JS,适合网页开发 |
5、小程序的双向绑定和 Vue 有什么不同?
- Vue:v-model直接双向绑定
- 小程序:需要绑定事件手动setData
1. 数据流控制逻辑
维度 | 微信小程序 | Vue |
---|---|---|
默认机制 | 单向数据流(父→子通过属性,子→父通过事件) | 双向绑定(v-model 语法糖) |
双向实现方式 | 需手动绑定事件(如 bindinput + setData ) | 直接通过 v-model 自动同步 |
数据更新 | 必须显式调用 this.setData() 更新 | 自动响应数据变化 |
本质区别:
小程序通过 事件系统 + API 调用 模拟双向绑定,而 Vue 通过 数据劫持/代理 实现自动响应式。
2. 语法设计差异
维度 | 微信小程序 | Vue |
---|---|---|
表单控件绑定 | 使用 value + bindinput 组合 | 直接使用 v-model |
自定义组件 | 需手动实现 properties + 事件触发 | 通过 model 选项或 v-model 参数化 |
指令系统 | 无指令概念,依赖事件绑定 | 提供 v-model 、v-bind 等指令 |
设计哲学:
小程序强调 显式数据流(更接近 React 模式),Vue 追求 声明式简化(隐式自动化)。
3. 底层实现原理
维度 | 微信小程序 | Vue |
---|---|---|
响应式原理 | 依赖 setData 的差量更新机制 | 基于 Object.defineProperty (Vue 2)或 Proxy (Vue 3) |
性能优化 | 需手动合并 setData 调用 | 自动批量异步更新 |
更新粒度 | 组件级别重渲染 | 精准到虚拟 DOM 节点 |
性能影响:
小程序的 setData
需要开发者手动优化调用频率,而 Vue 的响应式系统自动处理依赖追踪和批量更新。
进阶部分
1、小程序的运行机制是怎样的?(了解)
1. 框架结构
微信小程序采用了双线程模型,分别是逻辑层(App Service)和视图层(View)。这两个层次分别运行在不同的线程中,通过微信客户端提供的原生 API 进行通信。
-
逻辑层:负责处理业务逻辑、数据请求、页面路由等。使用 JavaScript 编写,运行在一个单独的线程中。
-
视图层:负责 UI 的渲染,使用 WXML 和 WXSS 来描述界面结构和样式。同样运行在一个独立的线程中,利用 WebView 渲染页面。
2. 加载流程
当用户打开一个微信小程序时,其加载过程大致如下:
-
小程序包被下载到本地设备(首次打开时)或从缓存中读取(后续打开)。
-
微信客户端启动逻辑层和视图层,并将
app.js
中的代码注入逻辑层线程执行,完成小程序的初始化工作。 -
根据初始页面路径,在逻辑层加载并执行相应的页面 JS 文件,同时在视图层加载对应的 WXML 和 WXSS 文件进行页面渲染。
3. 渲染机制
-
WXML 解析与渲染:视图层接收到逻辑层传递的数据后,会解析 WXML 文件,并根据数据动态生成页面结构。
-
WXSS 应用:同时应用 WXSS 样式规则对页面元素进行样式设置。
-
组件化开发:支持自定义组件,允许开发者封装可复用的 UI 组件,提高开发效率。
4. 数据更新与交互
-
当页面中的数据发生变化时,逻辑层会通知视图层进行重新渲染,确保界面与数据保持同步。
-
视图层可以通过事件绑定的方式向逻辑层发送用户交互信息(如点击按钮),从而触发相应的业务逻辑处理。
2、如何优化小程序的性能?
- 减少setData调用频率和数据量
- 使用分包加载
- 图片压缩
- 合理使用onPageScroll
优化方向 | 具体措施 | 原理/效果 | 注意事项 |
---|---|---|---|
代码体积控制 | 1. 使用分包加载(主包≤2MB,总包≤20MB) 2. 删除未使用的代码和资源 3. 压缩图片/代码(如TinyPNG、uglify) | 减少首次下载时间,提升启动速度 | 分包需在app.json 中配置路径 |
数据通信优化 | 1. 合并setData 调用2. 使用路径更新(如 setData({'a.b': value}) )3. 避免传输大对象(≤256KB) | 减少逻辑层与渲染层通信次数和传输量,降低延迟 | 高频操作(如滚动)避免频繁调用setData |
渲染性能 | 1. 列表渲染用wx:for +唯一key 2. 长列表用 recycle-view 虚拟列表3. 隐藏节点用 hidden 替代wx:if | 减少DOM节点数量,复用已有节点,避免重复渲染 | wx:if 会销毁组件,适合低频切换场景 |
启动加载 | 1. 启用预加载(preloadRule )2. 骨架屏(Skeleton Screen) 3. 异步初始化(延迟非必要逻辑) | 提前加载资源,提升页面切换速度;减少用户等待感知 | 预加载需平衡流量消耗与体验 |
图片/资源优化 | 1. 使用WebP格式图片 2. 懒加载图片( lazy-load 属性)3. CDN加速静态资源 | 减少资源体积和请求数,提升加载速度 | WebP需兼容iOS 14以下机型 |
事件处理 | 1. 防抖/节流(如lodash.throttle )2. 避免在 onPageScroll 中频繁操作 | 减少不必要的事件触发和逻辑层压力 | 滚动监听尽量轻量化 |
缓存策略 | 1. 数据缓存(wx.setStorage )2. 接口数据本地化(合理设置缓存时间) | 减少网络请求,加快二次访问速度 | 敏感数据避免缓存 |
原生组件优化 | 1. 避免过多原生组件(如video 、map )2. 动态加载原生组件(按需渲染) | 原生组件层级最高,过多会导致渲染性能下降 | 需处理遮盖问题(cover-view ) |
内存管理 | 1. 及时销毁定时器、事件监听 2. 使用 onUnload 清理全局变量 | 防止内存泄漏,提升长时间运行稳定性 | 尤其注意页面跳转时的资源释放 |
工具监控 | 1. 使用性能面板 2. 真机性能分析 | 定位瓶颈( |
3、小程序如何实现自定义组件?
- 创建组件目录
- 配置component: true
- 使用properties定义属性
- 父组件通过属性传递数据
面试回答模板(简洁版)
在微信小程序中实现自定义组件,首先需要创建一个组件文件夹,包含 WXML、WXSS、JS 和 JSON 文件。在 JSON 中声明 component: true
,在 JS 中定义 properties、data 和方法。然后在页面的 JSON 中通过 usingComponents
引入组件,就可以在 WXML 中使用。支持通过属性传值、事件通信和插槽分发内容,非常适合构建可复用的 UI 模块
步骤 | 操作说明 | 详细描述 |
---|---|---|
1. 创建组件文件夹 | 新建一个专门用于存放自定义组件的文件夹 | 在项目中创建一个目录(如 components/my-button ),用于存放组件的 WXML、WXSS、JS 和 JSON 文件。 |
2. 编写组件结构(WXML) | 定义组件的页面结构 | 使用 WXML 编写组件的模板内容,例如按钮、图标、文本等布局结构,支持数据绑定和事件绑定。 |
3. 编写组件样式(WXSS) | 定义组件的外观样式 | 使用 WXSS 为组件设置样式,样式默认具有局部作用域,不会影响其他页面或组件(除非使用全局样式)。 |
4. 编写组件逻辑(JS) | 定义组件的行为和数据 | 在 JS 文件中调用 Component({}) 方法定义组件,包含组件的属性(properties)、内部数据(data)、方法(methods)以及生命周期函数。 |
5. 配置组件(JSON) | 声明这是一个自定义组件 | 在组件的 JSON 文件中设置 "component": true ,告诉小程序这是一个自定义组件而非页面。 |
6. 在页面中引用组件 | 将组件注册到需要使用的页面 | 在页面的 JSON 配置文件中,通过 "usingComponents" 字段引入该组件,并指定组件标签名(如 my-button )。 |
7. 传递数据给组件 | 父组件向子组件传参 | 使用属性绑定语法(如 title="{{title}}" )将数据从页面传递给组件,组件通过 properties 接收并使用。 |
8. 组件向页面通信 | 子组件触发事件通知父组件 | 组件内部通过 this.triggerEvent() 触发自定义事件,页面通过事件绑定(如 bind:click )监听并处理。 |
9. 使用插槽(Slot) | 实现内容分发(类似 Vue 的 slot) | 如果希望在组件中插入外部内容,可以在 WXML 中使用 <slot> 标签,页面中的内容会自动插入到对应位置。 |
10. 组件生命周期 | 控制组件的创建、显示、销毁等行为 | 组件支持 created 、attached 、ready 、detached 等生命周期函数,可用于初始化数据或清理资源。 |
4、小程序的登录流程是怎样的?(了解)
面试回答模板(简洁版)
微信小程序的登录流程主要包括以下几个步骤:首先调用 wx.login()
获取临时登录凭证 code,然后将 code 发送到开发者服务器;服务器再向微信服务器请求用户的 openid 和 session_key;接着服务器根据这些信息生成自定义的登录态 token 并返回给小程序;之后小程序在每次请求时携带 token 来验证身份。这样可以实现安全、高效的用户登录机制。
1. 用户触发登录操作
-
用户在小程序端点击“登录”按钮或其他触发登录行为的操作。
2. 调用 wx.login()
获取临时登录凭证(code)
-
小程序通过微信提供的 API
wx.login()
获取一个临时登录凭证 code,这个 code 是一次性的、有效期为 5 分钟,且只能使用一次。 -
该 code 是微信服务器生成的,用于换取用户的唯一标识(openid)和会话密钥(session_key)。
3. 将 code 发送到开发者服务器
-
小程序将获取到的 code 发送给自己的后端服务器,通常通过 HTTP 请求(如
wx.request
)发送给后台接口。
4. 后端服务器向微信服务器请求用户信息
-
后端服务器使用 code 向微信服务器发起请求,调用微信的接口(
https://api.weixin.qq.com/sns/jscode2session
),传入小程序的appid
和appsecret
。 -
微信服务器验证通过后,返回用户的:
-
openid:用户的唯一标识(每个用户在每个小程序下唯一)
-
session_key:会话密钥,用于解密用户敏感数据(如手机号、加密信息)
-
5. 后端生成自定义登录态(token)
-
后端服务器根据用户的
openid
和其他信息生成一个自定义的登录态 token(如 JWT、session ID 等)。 -
这个 token 用于后续小程序与服务器之间的身份验证,代替原始的
session_key
,避免敏感信息泄露。
6. 返回 token 给小程序客户端
-
后端将生成的 token 返回给小程序客户端,小程序将 token 存储在本地(如
wx.setStorageSync
)。
7. 后续请求携带 token 验证身份
-
小程序每次请求业务接口时,在请求头或参数中携带该 token。
-
后端通过校验 token 判断用户身份,并返回相应的数据。
实战问题
1、小程序如何实现下拉刷新和上拉加载更多?(了解)
(1)实现下拉刷新(Pull Down Refresh)
1. 启用下拉刷新功能
-
在页面的
json
配置文件中设置"enablePullDownRefresh": true
,启用下拉刷新功能。 -
或者在全局
app.json
中设置,控制所有页面是否默认支持下拉刷新。
2. 监听下拉刷新事件
-
页面中定义
onPullDownRefresh
生命周期函数,当用户下拉页面时会自动触发该函数。 -
在该函数中通常会执行:
-
重置当前页码为第一页
-
清空当前数据列表
-
重新请求接口获取最新数据
-
数据加载完成后调用
wx.stopPullDownRefresh()
停止刷新动画
-
3. 停止刷新
-
数据加载完成后,必须手动调用
wx.stopPullDownRefresh()
来停止下拉刷新的 loading 动画,否则会一直显示。
(2)实现上拉加载更多(Reach Bottom)
1. 监听页面滚动到底部事件
-
页面中定义
onReachBottom
生命周期函数,当用户滚动到底部时自动触发。 -
通常用于加载下一页数据。
2. 实现分页加载逻辑
-
在该函数中执行:
-
当前页码自增(如 page + 1)
-
请求接口获取下一页数据
-
将新数据追加到已有数据列表中
-
如果没有更多数据,可以提示“没有更多了”或禁用后续加载
-
3. 控制加载频率(可选)
-
可以添加节流机制,防止短时间内多次触发加载
-
也可以设置一个标志位,如
isLoading = true
,防止重复请求
2、如何处理小程序的兼容性问题?(了解)
面试回答模板(简洁版)
小程序的兼容性问题主要体现在设备适配、微信版本、基础库、组件样式和接口数据等方面。
对于设备适配,使用 rpx 单位和 flex 布局,结合设备信息动态调整;对于不同微信版本,使用 wx.canIUse()
判断 API 支持情况,做降级处理;对于基础库版本,设置最低要求并封装兼容层;样式方面避免复杂选择器,组件使用注意层级问题;接口和数据方面做好字段容错和异常捕获。
(1)设备兼容性问题处理
1. 屏幕适配
-
使用
rpx
单位代替px
,rpx 是相对单位,可以根据屏幕宽度自动缩放,保证在不同尺寸设备上显示一致。 -
避免使用固定宽高值,尽量使用百分比、flex 布局、响应式设计。
2. 设备信息获取
-
使用
wx.getSystemInfoSync()
获取设备信息(如屏幕宽度、高度、像素比等),根据不同设备动态调整布局或样式。
3. 适配异形屏(如 iPhoneX 及以上)
-
使用
wx.getSystemInfoSync()
判断设备型号,对刘海屏、底部安全区域进行适配,避免内容被遮挡。 -
小程序原生组件支持
custom
模式,可以自定义导航栏,提升兼容性。
(2)微信客户端版本兼容性
1. 检查客户端版本
-
使用
wx.getSystemInfoSync()
获取微信客户端版本号,判断是否支持某些新特性或 API。
2. API 兼容性处理
-
对于某些新 API,使用
wx.canIUse()
判断当前客户端是否支持该 API,如果不支持,给出降级方案或提示。 -
例如:
wx.canIUse('button.open-type.contact')
可以判断是否支持打开客服按钮。
3. 渐进增强策略
-
核心功能在低版本也应可用,新特性作为增强体验使用,避免强依赖高版本功能。
(3)基础库版本兼容性
1. 设置最低库版本
-
在
app.json
中设置"requiredPrivateInfos"
或基础库版本限制,确保小程序运行在支持的库版本上。
2. 动态降级
-
对于不支持某些功能的旧库版本,可以通过判断版本号,动态隐藏或替换相关功能模块。
3. 使用兼容性插件或封装
-
将常用功能封装为兼容层,统一处理不同版本的差异,减少重复判断。
(4)组件和样式兼容性
1. 组件样式隔离
-
使用自定义组件时,注意样式作用域问题,避免样式污染。
-
可通过
styleIsolation
设置组件样式隔离级别。
2. 避免使用不兼容的 CSS 选择器
-
WXSS 支持的选择器有限,避免使用复杂 CSS 选择器(如
+
,~
,>
等)。 -
推荐使用类名控制样式,提高兼容性。
3. 原生组件兼容性
-
某些组件如
map
、video
是原生组件,层级固定,容易被遮挡,需注意 z-index 和布局结构。
(5)接口和数据兼容性
1. 接口兼容性
-
后端接口应保持向下兼容,新增字段不影响旧版本使用。
-
小程序端对返回字段做容错处理,避免因字段缺失导致崩溃。
2. 数据结构兼容
-
使用默认值处理可能缺失的字段,避免空值报错。
-
使用
try...catch
捕获解析异常,防止 JSON 解析错误。
3、小程序如何实现数据缓存?(了解)
面试回答模板(简洁版)
微信小程序提供了便捷的本地缓存功能,包括同步和异步两种方式。通过 wx.setStorageSync
和 wx.getStorageSync
可以简单地实现数据的存储和读取;而 wx.setStorage
和 wx.getStorage
则提供了异步操作的选择。每个小程序默认拥有 10MB 的缓存空间,虽然微信不自动清理缓存,但开发时应设计合理的缓存管理和同步策略,确保数据的一致性和有效性。
1. 同步存储与读取
-
存储数据:使用
wx.setStorageSync
方法将数据以键值对的形式同步存储到本地缓存中。 -
读取数据:通过
wx.getStorageSync
方法根据指定的键名同步读取本地缓存中的数据。 -
删除数据:利用
wx.removeStorageSync
方法根据键名同步删除本地缓存中的特定数据项。 -
清除所有数据:调用
wx.clearStorageSync
方法可以一次性清除所有的本地缓存数据。
2. 异步存储与读取
-
存储数据:采用
wx.setStorage
方法进行异步存储操作,支持回调函数来处理存储结果。 -
读取数据:使用
wx.getStorage
方法异步读取缓存数据,同样可以通过回调函数获取结果。 -
删除数据:通过
wx.removeStorage
方法异步删除指定键名的数据项。 -
获取所有键名:利用
wx.getStorageInfo
方法可以异步获取当前缓存的所有键名及其相关信息(如大小、数量等)。
3. 注意事项
-
缓存限制:每个小程序默认有 10MB 的本地缓存空间,超出限制会导致新的写入失败。
-
缓存有效期:微信小程序的本地缓存没有自动过期机制,需要开发者自行管理数据的有效性。
-
错误处理:无论是同步还是异步操作,都应该考虑异常情况下的错误处理,比如存储失败时给出相应的提示或者重试机制。
4. 最佳实践
-
数据一致性:确保本地缓存的数据与服务器端保持一致,尤其是在数据更新频繁的情况下,可能需要设计合理的同步策略。
-
缓存策略:根据实际需求选择合适的缓存策略,例如 LRU(最近最少使用)、TTL(生存时间)等,避免不必要的缓存占用。
-
用户体验优化:合理使用缓存可以显著提升应用的响应速度和用户体验,特别是在网络条件不佳的情况下。
4、小程序如何调用微信原生 API?
面试回答模板(简洁版)
微信小程序通过 wx.
开头的 API 提供原生功能支持,开发者只需按照规范传入参数和回调函数即可调用。例如 wx.request()
用于发起网络请求,wx.getLocation()
获取地理位置,wx.chooseImage()
选择图片等。调用时通常传入一个对象,包含 success、fail、complete 回调。需要注意部分 API 需要用户授权,调用前应检查授权状态并做好失败处理。
1. 了解 API 的使用规范
-
微信原生 API 都以
wx.
开头,如wx.request()
、wx.getLocation()
、wx.chooseImage()
等。 -
每个 API 都有对应的参数说明、成功回调、失败回调和完成回调。
-
部分 API 需要用户授权才能调用,如获取位置、相册、通讯录等信息。
2. 调用方式
-
微信原生 API 通常采用对象参数调用方式,传入一个包含参数和回调函数的对象。
-
一般支持以下字段:
-
success
:成功时的回调函数 -
fail
:失败时的回调函数(可选) -
complete
:无论成功或失败都会执行的回调(可选) -
其他具体参数,如 URL、数据、超时时间等
-
3. 调用流程(以 wx.request
为例)
用文字描述代码逻辑如下:
调用
wx.request
方法,传入一个包含请求地址、请求方法、请求头、请求数据的对象。在成功回调中处理返回的数据,在失败回调中提示用户网络错误或接口异常。
示例(文字描述代码):
-
使用
wx.request()
方法发送一个 GET 请求到指定的 URL。 -
设置
url
参数为接口地址,例如:https://api.example.com/data
-
设置
method
为'GET'
-
设置
success
回调函数,接收返回的数据,并更新页面数据或提示用户。 -
设置
fail
回调函数,提示用户网络异常或接口错误。
4. 授权类 API 的调用(如获取用户位置)
以调用
wx.getLocation()
为例:
-
调用
wx.getLocation()
方法,传入一个对象,指定返回的坐标类型(如 gcj02)。 -
如果用户之前未授权定位权限,系统会自动弹出授权提示。
-
成功回调中获取到经纬度等信息,可用于地图展示或业务逻辑。
-
失败回调中判断是用户拒绝授权还是其他错误,进行相应处理(如引导用户去设置授权)。
5. 文件和图片上传 API(如 wx.uploadFile
)
以
wx.uploadFile
为例:
-
调用
wx.uploadFile()
方法,设置上传的文件路径、服务器地址、上传字段名等参数。 -
成功回调中获取服务器返回的结果,如文件 ID 或 URL。
-
失败回调中提示用户上传失败或重试。
5、小程序如何实现分享功能?(了解)
面试回答模板(简洁版)
“微信小程序的分享功能主要通过 onShareAppMessage
生命周期函数实现。开发者可以在页面中定义该函数,返回分享的标题、图片和路径信息。用户点击右上角菜单或自定义按钮时,即可触发分享行为。此外,还可以通过 onShareTimeline
实现分享到朋友圈的功能。页面加载时,可以通过 options
参数获取分享来源,用于统计和分析用户行为。
(1)小程序分享功能的实现原理(文字说明)
1. 页面级分享功能
-
小程序默认在页面右上角菜单中提供“转发”按钮(即分享功能)。
-
开发者可以通过在页面 JS 文件中定义
onShareAppMessage
生命周期函数,来自定义分享的标题、图片、路径等信息。 -
当用户点击右上角菜单中的“转发”按钮时,微信会调用该函数并弹出分享面板。
2. 自定义按钮触发分享
-
除了右上角菜单,开发者还可以在页面中添加一个自定义按钮(如“分享给好友”),通过绑定点击事件来触发分享。
-
在按钮的点击事件中调用
wx.showShareMenu
或直接使用onShareAppMessage
定义的逻辑,实现自定义分享行为。
3. 分享内容的配置
-
在
onShareAppMessage
函数中可以返回一个对象,用于配置分享的:-
标题(title):分享卡片的标题
-
图片(imageUrl):分享卡片的缩略图
-
路径(path):分享跳转的页面路径(可携带参数)
-
内容(content):可选,部分场景下显示的简短描述
-
4. 分享后的行为追踪
-
微信提供了
onShareTimeline
函数用于支持“分享到朋友圈”的配置。 -
可以通过
wx.getLaunchOptionsSync()
或页面onLoad
中的options
参数获取分享带来的参数,用于统计分享来源或用户行为分析。
(2)实现步骤总结(文字版)
步骤 | 说明 |
---|---|
1. 启用分享菜单 | 默认开启右上角“转发”按钮,或通过 |
2. 定义分享内容 | 在页面中实现 |
3. 自定义按钮触发(可选) | 添加按钮并绑定事件,调用分享逻辑,提升用户点击率。 |
4. 支持朋友圈分享(可选) | 实现 |
5. 接收分享参数 | 页面加载时从 |
三、Uniapp 面试题
基础部分
1、Uniapp 是什么?它有什么优势?
Uniapp 是一个基于 Vue.js 的跨平台开发框架,开发者只需编写一套代码,即可编译到多个平台,包括但不限于:
- 微信小程序
- H5(Web)
- App(iOS 和 Android)
- 百度小程序
- 支付宝小程序
- QQ小程序
- 快应用
它极大地简化了多端开发的复杂度,让开发者能够更专注于业务逻辑的实现,而不是为每个平台单独开发和维护代码。
优势 | 描述 |
---|---|
一次编写,多端运行 | 使用 Vue.js 开发,一份代码可以同时编译成多个平台的应用,减少重复开发工作。 |
高效的开发体验 | 提供丰富的组件和API,支持Vue的语法糖,如v-model 、computed 等,提高开发效率。 |
强大的插件系统 | 支持通过插件扩展功能,例如支付、推送通知等功能,方便快捷地集成第三方服务。 |
良好的生态系统 | 拥有活跃的社区支持,大量的开源组件和模板可供选择,加速项目开发。 |
文档齐全 | 官方提供了详细的文档和教程,覆盖从基础到高级的各个方面,帮助新手快速上手。 |
2、Uniapp 如何实现多端兼容?
- 运行时根据不同平台编译为对应代码
- 条件编译处理平台差异
- 统一的API调用方式
面试回答模板(简洁版)
Uniapp 实现多端兼容的核心在于统一的开发语言(Vue)、统一的 API 调用方式和组件系统。所有平台都使用 Vue 语法开发,通过 uni.xxx()
调用统一接口,内部自动适配不同平台。同时,Uniapp 提供了条件编译机制,可以针对特定平台编写差异代码。构建时会根据目标平台自动转换代码格式,从而实现一次开发、多端运行。
步骤 | 说明 |
---|---|
1. 统一使用 Vue 语法开发 | 所有页面使用 Vue 的单文件组件结构进行开发。 |
2. 使用 uni API 替代原生 API | 所有接口调用统一使用 uni.xxx() 方法,屏蔽平台差异。 |
3. 使用通用组件进行布局 | 页面结构使用 Uniapp 提供的跨平台组件,如 <view> 、<text> 等。 |
4. 条件编译处理平台差异 | 遇到平台特有功能时,使用条件编译编写特定平台代码。 |
5. 编译构建目标平台代码 | 使用 HBuilderX 或命令行工具编译为指定平台的代码(如微信小程序、H5、App 等)。 |
6. 真机测试和调试 | 在不同平台上进行真机测试,确保功能和样式表现一致。 |
3、Uniapp 的生命周期有哪些?
- 应用生命周期:onLaunch, onShow, onHide
- 页面生命周期:onLoad, onShow, onReady, onHide, onUnload
- 组件生命周期:与Vue相同(beforeCreate → created → beforeMount → mounted → beforeUpdate → updated →beforeDestroy → destroyed)
面试回答模板(简洁版)
Uniapp 提供了应用和页面两个层次的生命周期钩子。应用级别的生命周期包括 onLaunch
、onShow
和 onHide
,分别在应用初始化、显示和隐藏时触发。页面级别的生命周期则更为丰富,包括 onLoad
、onShow
、onReady
、onHide
、onUnload
等,覆盖了页面从加载到卸载的全过程。此外,还有专门的钩子用于处理下拉刷新、滚动到底部、分享等功能。
(1)应用生命周期
应用生命周期指的是整个应用从启动到关闭的各个阶段。在 App.vue
文件中定义这些生命周期钩子。
生命周期钩子 | 描述 |
---|---|
onLaunch | 当应用初始化完成时触发(全局只触发一次)。常用于初始化操作,如用户登录检查、数据预加载等。 |
onShow | 当应用启动或从后台进入前台显示时触发。适用于处理应用重新激活时的操作。 |
onHide | 当应用从前台进入后台时触发。适合执行一些资源释放或状态保存的操作。 |
(2)页面生命周期
页面生命周期指的是单个页面从加载到卸载的各个阶段。在每个页面的 .vue
文件中定义这些生命周期钩子。
生命周期钩子 | 描述 |
---|---|
onLoad | 页面加载时触发,参数为页面跳转过来的参数。常用于根据传入参数初始化页面数据。 |
onShow | 页面显示/切入前台时触发。可用于刷新页面数据或恢复页面状态。 |
onReady | 页面初次渲染完成后触发。此时页面 DOM 已经准备好,适合进行一些依赖于 DOM 结构的操作。 |
onHide | 页面隐藏/切入后台时触发。适合暂停定时器、停止动画等操作。 |
onUnload | 页面卸载时触发。可用于清理资源或取消订阅等操作。 |
onPullDownRefresh | 监听用户下拉动作。通常用于实现下拉刷新功能。 |
onReachBottom | 页面滚动到底部时触发。常用于实现分页加载更多内容的功能。 |
onShareAppMessage | 用户点击右上角菜单“转发”按钮时触发。返回自定义的分享信息。 |
onPageScroll | 页面滚动时触发。参数包含页面滚动距离信息,适合监听滚动事件。 |
onTabItemTap | 点击 tab 时触发。参数包含被点击的 tab 信息。适用于底部导航栏相关的交互处理。 |
页面生命周期的特点:
-
页面生命周期钩子允许开发者更精细地控制页面的行为,特别是在页面加载、显示、隐藏和卸载的不同阶段。
-
某些钩子(如
onPullDownRefresh
、onReachBottom
)专为特定的交互场景设计,提供了丰富的用户体验增强手段。
4、Uniapp 如何调用原生功能?
在 UniApp 中调用原生功能主要通过 API 调用、条件编译 和 原生插件扩展 三种方式实现
5、Uniapp 的页面路由与微信小程序有什么不同?
-
路径写法:
- 微信小程序:
app.json
的pages
数组里写路径时不带文件后缀(如"pages/index/index"
)。 - UniApp:
pages.json
的pages
数组里写路径时必须带.vue
后缀(如"pages/index/index.vue"
)。
- 微信小程序:
-
路由跳转 API:
- 微信小程序:使用原生 API,如
wx.navigateTo({ url: '...' })
。 - UniApp:使用统一的
uni.navigateTo({ url: '...' })
等 API。这些 API 在编译时会被转换成对应平台(如微信小程序的wx.navigateTo
)的代码,实现了跨平台兼容。
- 微信小程序:使用原生 API,如
核心:UniApp 通过 uni.xxx
API 和 .vue
后缀的路径,在保持与小程序相似配置结构的同时,提供了跨平台能力。
进阶部分
1、Uniapp 如何实现条件编译?
// #ifdef H5
console.log('只在H5平台执行')
// #endif
// #ifdef MP-WEIXIN
console.log('只在微信小程序执行')
// #endif
2、Uniapp 如何优化多端应用的性能?
- 代码分割与懒加载:通过使用分包,可以将应用分割成多个较小的包,在需要时才进行加载。这样可以减少启动时间,提升用户体验。
- 图片资源优化:使用合适的图片格式(如 WebP),并根据设备分辨率提供不同大小的图片资源,以减少加载时间。
- 减少不必要的组件更新:合理使用
v-if
和v-show
,避免不必要的组件重绘和DOM操作。 - 使用原生组件:在可能的情况下,使用uni-app支持的原生组件来替代H5组件,因为它们通常具有更好的性能。
- 性能监控与分析:利用工具如小程序管理后台提供的性能分析工具,找出性能瓶颈,并针对性地进行优化。
3、Uniapp 如何实现原生插件开发?
- 准备环境:首先确保安装了HBuilderX最新版,并且配置好Android/iOS开发环境。
- 创建插件项目:可以通过HBuilderX创建一个uni-app插件项目,选择相应的平台(Android或iOS)。
- 编写原生代码:根据需求编写Java(Objective-C/Swift)代码实现功能,然后在uni-app中通过
uni.requireNativePlugin
调用这些本地方法。 - 打包发布:完成开发后,可以将插件打包上传至插件市场供其他开发者使用,或者直接集成到自己的项目中。
4、Uniapp 如何处理多端样式兼容问题?
- 使用条件编译:针对不同的平台使用
.scss
或.less
预处理器中的条件语句,或者直接在.vue
文件里使用<style platformName>
标签来写特定平台的样式规则。 - rpx单位:uni-app支持rpx作为响应式单位,它会根据不同设备的屏幕宽度自动调整尺寸,从而保证良好的视觉效果。
- Flex布局:尽量采用flex布局,因其能较好地适应不同尺寸的屏幕。
- 自定义变量与混合宏:利用CSS预处理器特性定义一些公共变量和混合宏,简化跨平台样式的维护工作。
5、Uniapp 如何实现热更新?
- 云函数/服务器端部署:首先需要有一个服务器来托管你的新版本应用资源(js、css等文件)。可以是自己的服务器,也可以使用云服务提供商的服务。
- manifest.json配置:在项目的
manifest.json
文件中开启热更新的相关设置,包括但不限于是否启用热更新、检查更新的周期等。 - 客户端检测更新逻辑:在应用启动时,添加逻辑去请求服务器检查是否有可用的新版本。如果有,则下载并应用更新。
- 注意事项:考虑到安全性和稳定性,建议先在一个小范围内测试热更新的效果,确保没有问题之后再推广给所有用户。同时,遵守各平台关于热更新的规定,以免被封禁。
实战问题
1、Uniapp 如何实现微信登录?
2、Uniapp 如何实现支付功能?
3、Uniapp 如何实现消息推送?
4、Uniapp 如何适配不同屏幕尺寸?
5、Uniapp 如何打包发布到不同平台?
四、跨框架问题
1、Vue、微信小程序和 Uniapp 在数据绑定方面的异同
- Vue:双向绑定,v-model
- 小程序:单向绑定,需手动setData
- Uniapp:类似Vue,但部分平台有限制
2、如何将 Vue 项目迁移到 Uniapp?
- Vue:双向绑定,v-model
- 小程序:单向绑定,需手动setData
- Uniapp:类似Vue,但部分平台有限制
3、Vue 组件和小程序/Uniapp 组件的区别
- 图片懒加载
- 减少DOM节点
- 节流防抖
- 合理使用缓存
- 避免频繁setData
4、如何解决跨平台开发中的样式兼容问题?
5、移动端开发中常见的性能优化手段有哪些?
6、如何实现一套代码适配多个平台?
7、H5、小程序和 App 开发的主要区别是什么?
8、如何调试多端应用?
9、你如何处理不同平台的 API 差异?
五、项目经验相关
1、你做过的最复杂的 Vue/小程序/Uniapp 项目是什么?遇到了什么挑战?
- 跨平台兼容性问题
- 性能优化(如长列表渲染)
- 与原生功能交互
- 多端UI一致性
2、你是如何解决跨平台兼容性问题的?
3、你在性能优化方面做过哪些工作?
- 使用虚拟列表优化长列表
- 图片压缩和懒加载
- 减少不必要的数据响应
- 合理使用缓存策略
4、你如何处理移动端的用户体验问题?
5、你是如何进行移动端测试的?
- 真机测试
- 多平台兼容性测试
- 性能分析工具
- 用户行为测试