海外推广渠道都有哪些,seo是什么软件,网站地图提交入口,客户关系管理系统功能目录 问#xff1a;uni-app 组件库的解决方案#xff1f;#xff08;xx 分钟#xff09;
必答
加分
深入
再深入
参考链接
问#xff1a;在 uni-app 中#xff0c;如何进行全局状态管理#xff1f;请介绍一下你对 Vuex 和 Pinia 的了解。
必答
加…目录 问uni-app 组件库的解决方案xx 分钟
必答
加分
深入
再深入
参考链接
问在 uni-app 中如何进行全局状态管理请介绍一下你对 Vuex 和 Pinia 的了解。
必答
加分
参考链接
问uni-app 中的组件和 Vue.js 中的组件有什么区别
必答
加分
深入
参考链接
问请介绍一下 uni-app 的网络请求库 uni.request 与 axios 相比它有哪些优缺点
必答
加分
参考链接
问为什么用 VSCode 开发 uni-app 项目而不使用 Hbuilder
必答
加分
参考链接
问如何在 uni-app 中实现自定义导航栏
必答
加分
深入
参考链接
问如何在 uni-app 项目中进行代码优化或性能优化
必答
加分
深入
再深入-防抖和节流
参考链接 uni-app 中如何实现下拉刷新和上拉加载更多功能
必答-下拉刷新
必答-分页加载
如何在 uni-app 中处理表单元素
必答
加分-表单校验
参考链接
问请谈谈你在使用 uni-app 过程中遇到的问题以及如何解决它们。
必答
参考链接
问请简述代码规范在团队协作中的重要性
必答
深入
问请介绍 uni-app 中的条件编译和平台差异化处理?
必答
加分 问uni-app 组件库的解决方案xx 分钟
必答
总我们项目使用的是 uni-ui 组件库这是官方出品的组件库有官方的技术支持和持续维护并且 uni-ui 组件库比较相对精简组件自动按需导入有利于减小项目体积。
分两个核心步骤是
安装 dcloudio/uni-ui(组件库) 和 scss。在 pages.json 文件中配置 easycom 规则实现 uni-ui 组件的自动导入和注册。
加分
虽然 uni-ui官方并没有类型声明文件但我们在项目中还配置了 uni-ui 的 TS 组件类型支持可以校验组件的属性类型更安全书写时也有代码提示。
实现类型支持其实也就多了两个步骤
安装 uni-helper/uni-ui-type 第三方类型声明文件。再配置 tsconfig.json将类型声明文件添加到 types 数组就可以了。
深入 TIP 准备充分的同学可以自己融入加分回答中或者引导面试官往自己准备的方向提问。 其实 uni-app 和 uni-ui 目前还没有 TS 官方支持所以默认情况下组件是没有类型校验的如果自己手写组件类型声明效率太低了。基于这个问题我们团队做过一些充分的调研uni-helper 虽然是非官方组织但这个第三方组织是 uni-app 生态类型声明文件做的非常好更新频率也非常及时。其实在我们开发的过程中遇到些小问题我们在 github 仓库提的 issue 也有及时解决。最后我们也保持关注官方文档和更新确保项目的稳定性和兼容性。
再深入 ❓ 问: 为什么项目中使用 uni-ui 而不选择 uview-ui。 ♂️ 答: 我们团队主要是考虑以下三点做出的选择 uni-ui 是官方出品的组件库有官方的技术支持和持续维护(最重要)。uni-ui 比较相对精简有利于减小项目体积。uview-ui 暂不支持 Vue3 开发稍微落后。
当然 uview-ui 组件库也不错是目前 uni-app 插件市场下载量最高的第三方 Vue2 组件库社区中也有热心的小伙伴为 uview-ui 做了 Vue3 版但目前可能作者太忙了处于没更新状态不稳定所以综合考虑我们选择官方维护的 uni-ui。
参考链接
uni-ui 组件库uview-ui 组件库vk-uview-ui 组件库-不更新uni-helper 组织uni-ui-types 类型声明uni-helper 组织的 VS Code 插件-下载量 14kuView有计划支持 vue3.0 吗
类似问题 如何在 uni-app 中引入和使用第三方组件库请介绍几个常用的 uni-app 组件库以及它们的特点和使用场景组件库的 TS 类型怎么处理 问在 uni-app 中如何进行全局状态管理请介绍一下你对 Vuex 和 Pinia 的了解。
必答
总我们项目使用的是 Pinia 进行全局状态管理Vuex 或 Pinia 都是官方提供的状态管理库。
分我先说一下我对 VueX 的了解 Vuex 采用单一状态树的概念将全局状态集中管理方便追踪状态变化。Vuex 主要包含以下几个核心概念
State用于存储全局状态。Getter用于从 State 中派生出一些状态例如计算属性。Mutation用于同步修改 State严格遵循单向数据流。Action用于异步操作可以包含异步 API 请求、异步提交 Mutation 等。
我对 Pinia 的了解是 Pinia 可以理解为就是 Vuex5是一个轻量级的、兼容 Vue 3 和 Vue 2 的状态管理库。Pinia 和 VueX 主要区别是废弃了经常被认为是极其冗余的 mutationPinia 主要包含以下几个核心概念
Store用于存储全局状态和处理状态变化的方法类似于 Vuex 的 State、Getter 和 Action 的集合。可以创建和使用多个 Store 实例每个 Store 都有自己独立的状态和方法。
总所以我们项目最终选择的是 Pinia 进行全局状态管理。
加分
总其实我们的项目还配置了 pinia 的持久化存储方案。
分我们用到了 pinia-plugin-persistedstate 插件实现持久化周下载量 61k但是这个插件默认使用 localStorage 实现持久化小程序端不兼容所以必须修改一下配置替换为 uni-app 支持多端的持久化 API也就是 uni.setStorageSync() 和 uni.getStorageSync()。
总持久化存储配置完成后就会自动将用户数据保存在客户端即使用户关闭了小程序数据依然可以保留。
配置参考
// stores/modules/member.ts
export const useMemberStore defineStore(member,() {//…省略},{// 配置持久化persist: {// 调整为兼容多端的APIstorage: {setItem(key, value) {uni.setStorageSync(key, value) },getItem(key) {return uni.getStorageSync(key) },},},},
) 参考链接
Vuex 官方文档Pinia 官方文档Pinia 对比 Vuex 3.x/4.x 官方说明pinia-plugin-persistedstate 插件的 storage 配置 类似问题 在 uni-app 中如何实现全局状态管理在 uni-app 中如何实现持久化存储 问uni-app 中的组件和 Vue.js 中的组件有什么区别
必答
总uni-app 是基于 Vue.js 构建的跨平台开发框架因此 uni-app 中的组件与 Vue.js 中的组件在很多方面是相似的。然而由于 uni-app 需要支持多个平台包括微信小程序、App 端和 H5 端所以在某些方面会有一些差异。
分根据自身理解选其中几点回答即可
以下是 uni-app 中的组件与 Vue.js 中的组件的一些主要区别 跨平台Vue.js 主要用于开发网页应用而 uni-app 可以让你用同一套代码开发微信小程序、App、H5 等多个平台的应用。 基础组件uni-app 提供了一套与 Vue.js 不同的基础组件。这些组件是为了适应不同平台的 UI 要求而设计的它们在微信小程序、App 端和 H5 端上有统一的表现。在使用这些组件时需要注意它们在不同平台之间的差异封装自定义组件的时候更推荐 view、text 等基础组件而非 div、span。 生命周期虽然 uni-app 和 Vue.js 的组件都有生命周期钩子但是 uni-app 为了适应不同平台而引入了一些额外的生命周期钩子例如 onLaunch、onShow 和 onHide。 样式差异某些 CSS 选择器不受支持如 * 通配符选择器。此外uni-app 支持一种叫做 rpx 的相对单位它可以自动适应不同屏幕尺寸。 条件编译由于 uni-app 支持多个平台所以提供了条件编译功能。开发者可以通过条件编译在特定平台上使用平台特有的 API 或组件从而实现平台相关的功能。
总总的来说uni-app 和 Vue.js 的组件在很多方面是相似的但是由于 uni-app 需要支持多个平台所以在一些细节上会有所区别平时开发时要注意平台相关的组件、生命周期、样式的差异。
加分
可以展开 uni-app 生命周期分为三部分
应用生命周期与 小程序 应用的生命周期一致onLaunch、onShow、onHide 等页面生命周期与 小程序 页面的生命周期一致onLoad、onUnload、onShow 等组件生命周期与 Vue.js 组件的生命周期一致mounted、created 等
我们的购物车页面需要借助 onShow 生命周期钩子获取最新的购物车列表数据因为在商品详情页中进行添加购物车操作。添加成功后打开购物车页面应展示最新的购物车数据。因此每次 购物车页面 onShow 时都应获取最新的购物车列表数据。收货地址列表页同理。
深入
总小程序是一个独立的应用平台有自己的一套生命周期如 onLaunch、onShow、onHide在 uni-app 项目还支持 Vue 的生命周期钩子。
分 onLaunch 生命周期钩子在 App.vue 根组件中就类似 created 或 mounted 钩子。 Vue.js 本身并没有提供 onShow 和 onHide 生命周期钩子但是可以通过监听页面的 visibilitychange 事件来模拟实现这两个钩子。从而在一定程度上模拟 onShow 和 onHide 的行为。
总我们的 uni-app 项目主要是做小程序端所以我们的页面组件优先使用小程序的生命周期钩子也就是 onShow、onHide 这些普通组件就用 Vue 生命周期钩子。
参考代码
mounted() {document.addEventListener(visibilitychange, this.handleVisibilityChange);
},
beforeDestroy() {document.removeEventListener(visibilitychange, this.handleVisibilityChange);
},
methods: {handleVisibilityChange() {if (document.hidden) {this.onHide();} else {this.onShow();}},onShow() {console.log(页面显示);},onHide() {console.log(页面隐藏);}
}
这样当页面变为隐藏状态时onHide 方法会被调用当页面重新显示时onShow 方法会被调用。
注意在组件销毁时要记得移除 visibilitychange 事件监听以避免内存泄漏。
参考链接
uni-app 应用生命周期uni-app 页面生命周期uni-app 组件生命周期WebAPI - visibilitychange 事件 类似问题 uni-app 与 Vue 区别在 uni-app 中实现自定义组件有什么区别吗在 uni-app 中如何处理 CSS 样式的差异请介绍 uni-app 的生命周期函数以及它们在不同平台下的差异。谈谈 uni-app 组件的生命周期以及它们与 Vue.js 组件生命周期的异同。如何实现 uni-app 中的跨平台开发请谈谈 uni-app 的条件编译。 问请介绍一下 uni-app 的网络请求库 uni.request 与 axios 相比它有哪些优缺点
必答
总uni-app 的 uni.request 是一个用于发起网络请求的 API。它是 uni-app 框架内置的网络请求库兼容多端包括小程序、App、H5 等无需额外安装。使用 uni.request 可以发起 GET、POST、PUT、DELETE 等 HTTP 请求。
分与 axios 相比uni.request 的优缺点如下
优点
内置于 uni-app 框架不需要额外安装和引入第三方库。兼容多端可以方便地在不同平台上使用。
缺点
功能相对于 axios 较为简单缺少一些高级功能例如拦截器需要自己实现。错误处理不如 axios 完善。axios 可以轻松区分网络错误和业务错误而在 uni.request 中需要手动判断状态码。
总其实在我们的项目中也借鉴 axios 的思想基于 uni.request 封装了自己的网络请求库可以用于处理常见的请求场景。
加分
总我们自己实现了一个基于 uni-app 的网络请求库。通过添加拦截器实现了对请求前处理和请求后的处理提高了代码的复用性。
分具体来说代码实现了以下功能
添加拦截器拦截 request 请求和 uploadFile 文件上传。非 http 开头的请求 URL 自动拼接基础地址 baseURL。如果存在 token则将其添加到请求头 Authorization。封装了一个 http 函数该函数返回一个 Promise 对象支持泛型方便处理返回数据的类型。当请求成功时状态码为 2xx执行 resolve() 表示成功并提取核心数据res.data。当请求失败时 如果状态码为 401则清除用户信息并跳转到登录页面。如果是其他错误则根据后端错误信息进行提示。如果是网络错误则提示用户更换网络。
总我们借鉴 axios 的思想基于 uni.request 封装了自己的网络请求库可以用于处理常见的请求场景。
参考代码
import { useMemberStore } from /stores// 服务器基地址
const baseURL https://pcapi-xiaotuxian-front-devtest.itheima.net// 添加拦截器
const httpInterceptor {// 拦截前触发invoke(options: UniApp.RequestOptions) {// 1. 非 http 开头需拼接地址if (!options.url.startsWith(http)) {options.url baseURL options.url}// 2. 请求超时, 默认 60soptions.timeout 10000// 3. 添加小程序端请求头标识options.header {...options.header,source-client: miniapp,}// 4. 添加 token 请求头标识const memberStore useMemberStore()const token memberStore.profile?.tokenif (token) {options.header.Authorization token}},
}// 添加拦截器
uni.addInterceptor(request, httpInterceptor)
uni.addInterceptor(uploadFile, httpInterceptor)type DataT {code: stringmsg: stringresult: T
}
// 2.2 添加类型支持泛型
export const http T(options: UniApp.RequestOptions) {// 1. 返回 Promise 对象return new PromiseDataT((resolve, reject) {uni.request({...options,// 响应成功success(res) {// 状态码 2xx axios 就是这样设计的if (res.statusCode 200 res.statusCode 300) {// 2.1 提取核心数据 res.dataresolve(res.data as DataT)} else if (res.statusCode 401) {// 401错误 - 清理用户信息跳转到登录页const memberStore useMemberStore()memberStore.clearProfile()uni.navigateTo({ url: /pages/login/login })reject(res)} else {// 其他错误 - 根据后端错误信息轻提示uni.showToast({icon: none,title: (res.data as DataT).msg || 请求错误,})reject(res)}},// 响应失败fail(err) {uni.showToast({icon: none,title: 网络错误换个网络试试,})reject(err)},})})
} 参考链接
uni.request 网络请求
uni.uploadFile 上传文件
uni.addInterceptor 拦截器
拓展阅读 - uni 拦截器其他用法 问为什么用 VSCode 开发 uni-app 项目而不使用 Hbuilder
必答
总其实 Hbuilder 我也有使用不过最终体验下来还是选择了 VS Code 。
分我主要是有 2 个出发点考虑
熟悉度VSCode 是我最熟悉并习惯使用的代码编辑器常用的代码片段快捷键可以我的开发效率。插件生态我针对 uni-app 项目安装了对应的插件代码提示快速新建页面并注册路由鼠标悬停查文档这些功能我都在 VSCode 找到对应的插件非常好用。
总其实还是我自己不想换开发工具也不是刻意去比较两者谁好谁坏哪一个编辑器自己用起来更习惯能提高效率就用哪个。
温馨提示Hbuilder 编辑器对 TS 的类型支持还不够完善就好比 image 组件的 mode 取值写错了之前用 Hbuilder 的时候校验不出来而 VSCode 可以校验出错误期待 Hbuilder 的进步。如果面试官特别喜欢用 Hbuilder 就不建议提这个尊重每个人的喜好
加分
如果面试官对 VS Code 的配置感兴趣可以继续展开如何配置
总用 VS Code 开发 uni-app 进行 3 步配置就可以了也可以给面试官您分享一下
分 安装 uni-app 插件 uni-create-view 快速创建 uni-app 页面uni-helper uni-app 代码提示uniapp 小程序扩展 鼠标悬停查文档 JSON 注释报错问题设置文件关联即可把 manifest.json 和 pages.json 设置为 jsonc 针对 TS 项目增加 TS 类型校验 安装类型声明文件 pnpm i -D miniprogram-api-typings uni-helper/uni-app-types配置 tsconfig.json
总 HBuilder 也有它的优点针对 uni-app 开发的专属功能、内置的调试工具如果要打包和调试 App 端还要用到 Hbuilder 工具。选择哪一个编辑器写代码取决于开发者的个人喜好和项目需求。
参考链接
uni-helper 插件uni-create-view 插件VSCode 开发 uni-app 教程-Vue2 版 问如何在 uni-app 中实现自定义导航栏
必答
我们项目的首页订单详情页个人信息页等页面都用到了自定义导航栏核心步骤如下
隐藏默认导航栏在 pages.json 文件中按需设置 navigationStyle 为 custom 。按设计稿要求编写自定义导航栏的结构、样式和脚本。封装左上角返回按钮通过 getCurrentPages 获取路由栈如果路由栈数组长度只有 1通过 switchTab 返回首页其他情况应该是用 navigateBack 返回上一页。最后还可以根据需要抽离封装成一个通用的组件预留标题插槽等方便复用。
如果自定义导航栏要求不高其实也可以直接用 uni-ui 的 uni-nav-bar 或者从 插件市场 中下载与项目要求接近的插件再进行二次开发适配自己的项目。
加分
我们项目中的自定义导航栏其实还做了安全区的样式适配通过 uni.getSystemInfoSync() 获取顶部到安全区的距离在模板中绑定行内样式避免刘海屏或前置摄像头遮挡导航栏标题或 logo 等重要内容。
如果左侧按钮要对齐右侧的胶囊还可以通过 wx.getMenuButtonBoundingClientRect 获取胶囊信息实现对齐。
参考代码
// src/pages.json
{path: pages/index/index,style: {navigationStyle: custom // 隐藏默认导航}
} !-- CustomNavbar.vue --
script setup langts
// 获取页面栈
const pages getCurrentPages()
// 获取屏幕边界到安全区域距离
const { safeAreaInsets } uni.getSystemInfoSync()
/scripttemplate!-- 顶部安全区占位 --view classnavbar :style{ paddingTop: safeAreaInsets?.top px }view classwrapnavigatorv-ifpages.length 1open-typenavigateBackclassback icon-left/navigatornavigator v-else url/pages/index/index open-typeswitchTab classback icon-home/navigatorview classtitle!-- 插槽 --slot导航栏标题/slot/view/view/view
/template
深入
其实我们项目的订单详情页或者某个页给自定义导航栏加了滚动驱动动画增强用户视觉效果
scroll-view 滚动容器设置一个 id用于绑定动画效果和滚动容器偏移量。获取当前页面实例因为这个功能目前只有微信小程序端支持H5 端不支持还需要写条件编译。onReady 绑定生命周期钩子中通过 animate 设置动画配置并通过 id 绑定滚动容器设置触发偏移量等信息。
\
script setup langts
// 获取屏幕边界到安全区域距离
const { safeAreaInsets } uni.getSystemInfoSync()
// 获取页面栈
const pages getCurrentPages()// #ifdef MP-WEIXIN
// 获取当前页面实例数组最后一项
const pageInstance pages.at(-1) as any// 页面渲染完毕绑定动画效果
onReady(() {// 动画效果,导航栏背景色pageInstance.animate(.navbar,[{ backgroundColor: transparent }, { backgroundColor: #f8f8f8 }],1000,{scrollSource: #scroller,timeRange: 1000,startScrollOffset: 0,endScrollOffset: 50,},)
})
// #endif
/scripttemplate!-- 自定义导航栏: 默认透明不可见, scroll-view 滚动到 50 时展示 --view classnavbar :style{ paddingTop: safeAreaInsets?.top px }view classwrapnavigatorv-ifpages.length 1open-typenavigateBackclassback icon-left/navigatornavigator v-else url/pages/index/index open-typeswitchTab classback icon-home/navigatorview classtitle订单详情/view/view/viewscroll-view classviewport scroll-y enable-back-to-top idscroller...滚动容器/scroll-view
/template
参考链接
uni-nav-bar 自定义导航栏插件市场 自定义导航栏获取系统信息滚动驱动的动画 问如何在 uni-app 项目中进行代码优化或性能优化
必答
总其实代码优化和性能优化是一个持续进行的过程我们的项目主要是做了以下的优化
分根据自身理解选其中几点回答即可大部分其实在项目中都有体现
页面加载优化 按需加载使用图片懒加载只在需要时加载商品图片添加 lazy-load 属性即可。分包加载项目模块拆分为多个包按需加载对应的包降低初始加载时间。项目的分包分包页面的图片等资源也可放到分包的文件夹中减少主包资源体积代码优化 代码分层按功能模块化代码提高代码可读性和可维护性goods.ts、home.ts 等划分。使用枚举枚举提供了一种更有意义的命名方式使代码更具可读性类型也更安全 。条件编译在处理多端的时候按条件编译平台所需代码减少冗余。登录界面等类型安全为组件 TS 提供了静态类型检查有助于在编译阶段发现潜在的类型错误。这可以减少运行时错误提高代码的可靠性。(安装 uni-app-types、uni-ui-types)数据处理优化 数据获取仅获取和处理需要的数据避免不必要的数据处理分页时设计合理的页容量减少一次性渲染的节点数量。 如订单列表的容量为 5因为订单信息较多实际情况是屏幕大概能放 3 个数据缓存缓存获取的数据减少不必要的数据请求配置持久化存储。优化数据更新在 uni-app 中定义在 data/ref 里面的数据每次变化时都会通知视图层重新渲染页面。所以如果不是视图所需要的变量可以不定义在 data/ref 中可定义普通变量以避免造成资源浪费。如分页的参数仅用于发送请求和判断条件不用于界面渲染没有用 ref 定义这份变化的数据组件化开发 组件复用对于通用功能将其封装为组件提高代码复用性。猜你喜欢组件轮播图组件优化资源文件 减少本地图片除了 tabBar 图片logo 等重要的图片其他图片进可能使用 CND 图片。压缩图片避免使用大图对图片进行压缩减少图片文件大小。素材已压缩尺寸在线压缩图片网络环境适配获取设备的网络类型可以在应用中根据网络环境做出相应调整如在较慢的网络环境下降低图片质量、限制大文件下载等。使用 CDN 加速 将静态资源文件放在 CDN 上加速资源文件的加载速度。公司已购买由运维管理项目商品图都已开启 CDN 加速页面渲染优化 使用条件渲染语句如 wx:if合理控制组件渲染减少不必要的组件渲染。空购物车订单状态等v-if 可以减少 DOM 树的大小从而减少重绘成本而 v-show 通过 CSS 来控制显示适用于频繁切换的场景。避免不必要的组件重绘减少不必要的数据变动避免组件频繁重绘。v-for 的 key 值有助于 Vue 识别和复用已存在的元素减少重绘次数。v-if、v-show 的合理使用也是减少重绘成本骨架屏提升用户体验使用户感知到数据正在加载降低用户等待时的焦虑感避免页面白屏闪烁。(微信开发者工具自动生成项目首页和部分请求数据量较大的页面记得添加骨架屏)避免视图层和逻辑层频繁进行通讯减少 scroll-view 组件的 scroll 事件监听注意 onPageScroll 的使用。项目中没有使用 scroll 和 onPageScroll如果一定要使用可以添加防抖 减少视图层频繁渲染防抖和节流函数 lodash 都有现成的多使用组件自带动画css 动画而不是通过 js 的定时器操作界面做动画swiper 滑动动画是自带的订单列表页 Tabs 的滑块使用了 css 动画滚动驱动的动画是小程序自带的并非手动监听 scroll 事件优化网络请求 使用请求拦截和响应拦截对请求和响应进行拦截处理提高请求效率。http.ts 的封装
总总的来说性能优化是一个持续进行的过程通过不断地优化和调整提高项目的性能和用户体验。
加分
理论上越多越好按照自己的理解情况回答回答时可提及项目中的业务场景适当展开。
深入
如何在 uni-app 项目中使用使用防抖或节流函数。
安装 lodash 工具库 pnpm i lodash在 TS 项目中安装类型声明文件 pnpm i -D types/lodash。导入 debounce 防抖函数。用 debounce 函数包裹原事件函数并设置合理的延迟时间结合真机调试取合适毫秒值。
参考代码
组合式 API 写法
script setup langts
import { throttle } from lodash
import { ref } from vue// 响应式数据
const scrollTop ref(0)// 普通的事件函数
const onScroll2 (ev: UniHelper.ScrollViewOnScrollEvent) {// 触发频率非常高视图层频繁渲染scrollTop.value ev.detail.scrollTop
}// 添加节流的事件函数
const onScroll throttle((ev: UniHelper.ScrollViewOnScrollEvent) {// 在 100 秒内最多执行一次函数更新视图层scrollTop.value ev.detail.scrollTop
}, 100)
/scripttemplate!-- 滚动容器 --scroll-view scroll-y scrollonScroll!-- 打印坐标 --view styleposition: fixed; top: 100rpx; left: 50rpx; background-color: pinkscrollTop:{{ scrollTop }}/viewview styleheight: 5000rpx 内容 /view/scroll-view
/template
选项式 API 写法
script langts
import { debounce } from lodash
import { defineComponent } from vueexport default defineComponent({data() {return {scrollTop: 0,debouncedScroll: null as any,}},created() {// 防抖的处理函数适当延迟 50 毫秒后再更新视图层this.debouncedScroll debounce(this.onScroll, 50)},unmounted() {// 最好是在组件卸载时,清除掉防抖计时器this.debouncedScroll.cancel()},methods: {// 普通的事件处理函数onScroll(ev: UniHelper.ScrollViewOnScrollEvent) {this.scrollTop ev.detail.scrollTop},},
})
/scripttemplate!-- 滚动容器 --scroll-view scroll-y scrolldebouncedScroll!-- 打印坐标 --view styleposition: fixed; top: 100rpx; left: 50rpx; background-color: pinkscrollTop:{{ scrollTop }}/viewview styleheight: 5000rpx 内容 /view/scroll-view
/template
再深入-防抖和节流
(总) 防抖debounce和节流throttle函数在处理高频触发事件时都非常实用。
debounce防抖函数该函数会从上一次被调用后延迟 wait 毫秒后调用func 函数。
throttle 节流函数在 wait 秒内最多执行 func 一次的函数。
根据自身理解选其中几点回答即可
分 1防抖debounce函数在以下应用场景中非常实用
输入框实时搜索当用户在输入框中输入时可以使用防抖函数来延迟触发搜索请求。这样可以减少服务器请求次数提高性能。按钮点击在一些场景下如表单提交、购物车结算等为避免用户频繁点击按钮导致重复提交数据可以使用防抖函数控制按钮点击事件的触发。滚动事件在处理滚动事件时可以使用防抖函数来限制事件处理函数的执行频率。例如当用户滚动页面时可以使用防抖函数来延迟加载图片或触发其他与滚动相关的操作。用户操作监听在实时监控用户操作如鼠标移动、点击等的场景中可以使用防抖函数来减少事件处理函数的执行次数降低系统资源消耗。
分 2节流throttle函数在以下应用场景中非常实用
滚动加载在无限滚动列表或页面滚动加载数据的场景中可以使用节流函数控制滚动事件处理函数的执行频率以减轻服务器压力和提高性能。组件库一般有实现页面滚动时的动画效果当用户滚动页面时可以使用节流函数来控制动画效果的触发频率以保持流畅的动画表现避免性能抖动。微信小程序的滚动驱动动画内部实现实时监控鼠标移动在需要实时监控鼠标移动的场景中可以使用节流函数限制事件处理函数的执行频率降低系统资源消耗。浏览器窗口大小调整当用户调整浏览器窗口大小时可以使用节流函数来限制与窗口大小相关的布局调整或重绘的执行频率提高页面性能。实时数据采集在需要实时采集用户行为数据的场景中可以使用节流函数来控制数据发送频率减轻服务器压力。
总虽然防抖和节流的应用场景看似有所重叠但它们的工作原理和应用场景有所不同
工作原理
防抖debounce当事件触发后防抖函数会等待一定时间设定的延迟时间如果在这段时间内事件没有再次触发则执行事件处理函数。如果在这段时间内事件再次触发那么重新开始等待延迟时间。简单来说防抖就是让事件处理函数在事件触发后的一段时间内不执行只有当事件停止触发一段时间后才会执行。
节流throttle节流函数会在一定时间间隔内执行事件处理函数即使在这段时间内事件多次触发也只会执行一次事件处理函数。简言之节流就是让事件处理函数以固定的频率执行。
应用场景
它们在不同的场景下有各自的优势
防抖适用于需要等待一段时间后才执行的场景如搜索框输入实时搜索、按钮点击避免重复提交等。这些场景中只关心事件触发的最后一次而不关心事件在中间的过程。
节流适用于需要以一定频率执行的场景如滚动加载、窗口大小调整、鼠标移动监控等。这些场景中关心事件在整个过程中的表现而不仅仅是最后一次触发。
总结防抖关注事件触发后的延迟执行节流关注事件在整个过程中以固定频率执行。在选择使用防抖或节流时需要根据具体的应用场景和需求来决定。
参考链接
uni-app 优化建议-官方整理智能 WebP, PNG 和 JPEG 压缩防抖的事件处理器 - Vue 官方文档创建一个防抖 ref - Vue 官方文档lodash 防抖 debounce 函数用法lodash 节流 throttle 函数用法 类似问题 请谈谈如何在 uni-app 中实现页面的按需加载请谈谈防抖和节流的理解和应用场景 uni-app 中如何实现下拉刷新和上拉加载更多功能
参考首页的下拉刷新猜你喜欢组件和热门推荐页的上拉加载分页。
必答-下拉刷新
我们是通过 scroll-view 组件 实现的下拉刷新步骤如下
启用下拉刷新 添加 refresher-enabled 属性。下拉刷新事件绑定 refresherrefresh 事件。添加 下拉刷新状态 标记 添加 refresher-triggered 属性用于关闭动画的。下拉刷新事件内部主要是重新获取数据当数据获取成功后主动关闭下拉刷新动画。注意在多个请求的情况下需要用 Promise.all() 等所有请求都结束了再关闭动画
script setup langts
// 当前下拉刷新状态
const isTriggered ref(false)
// 自定义下拉刷新被触发
const onRefresherrefresh async () {// 开始动画isTriggered.value true// 加载数据await Promise.all([getHomeBannerData(), getHomeCategoryData(), getHomeHotData()])// 关闭动画isTriggered.value false
}
/scripttemplate!-- 滚动容器 --scroll-viewrefresher-enabledrefresherrefreshonRefresherrefresh:refresher-triggeredisTriggeredscroll-y..../scroll-view
/template 必答-分页加载
上拉加载更多其实就是分页加载主要步骤如下。
定义 pageParams 对象存储分页参数包括页码 page 和每页数据量 pageSize。定义 finish 响应式引用表示是否已加载完所有数据。滚动触底事件给 scroll-view 组件绑定 scrolltolower 事件。在事件内部需要判断是否已加载完所有数据没有结束就继续发送请求同时页码要累加获取的数据要追加到原数组后如果分页已结束就更新 finish 标记并提醒用户。
script setup langts
// 分页参数
const pageParams: RequiredPageParams {page: 1,pageSize: 10,
}
// 猜你喜欢的列表
const guessList refGuessItem[]([])
// 已结束标记
const finish ref(false)
// 获取猜你喜欢数据
const getHomeGoodsGuessLikeData async () {// 退出分页判断if (finish.value true) {return uni.showToast({ icon: none, title: 没有更多数据~ })}const res await getHomeGoodsGuessLikeAPI(pageParams)// 数组追加guessList.value.push(...res.result.items)// 分页条件if (pageParams.page res.result.pages) {// 页码累加pageParams.page} else {finish.value true}
}
// 重置数据
const resetData () {pageParams.page 1guessList.value []finish.value false
}
// 组件挂载完毕
onMounted(() {getHomeGoodsGuessLikeData()
})
/scripttemplate!-- 滚动容器 --scroll-view scrolltoloweronScrolltolower scroll-y!-- 猜你喜欢列表 --view classguessnavigatorclassguess-itemv-foritem in guessList:keyitem.id:url/pages/goods/goods?id${item.id}image classimage modeaspectFill :srcitem.picture/imageview classname {{ item.name }} /viewview classpricetext classsmall¥/texttext{{ item.price }}/text/view/navigator/viewview classloading-text{{ finish ? 没有更多数据~ : 正在加载... }}/view/scroll-view
/template
如何在 uni-app 中处理表单元素
必答
在我们项目的个人信息页收货地址表单页等页面都涉及到表单数据的收集。
总在 uni-app 中使用的是 input、radio 、checkbox 和 picker 等组件能兼容不同平台。
分
input 支持 v-model 双向绑定收集数据比较便利。radio 、checkbox 和 picker 等不支持 v-model 指令可以使用 :value 和 change 代替 v-model 来实现类似的效果。
总 小程序端的表单组件具有一些特有的属性外观和功能都有些差异如 input 组件的 type 属性支持的值与网页端有所不同。例如小程序端的 input 组件有一个 idcard 类型而网页端没有。所以不要完全凭借网页端的经验处理小程序的表单尽管部分表单组件的名称和网页端同名也要应该要查阅 uni-app 组件部分的文档了解差异。
参考代码
script setup langts
import { ref } from vueconst switchValue ref(false)const onSwitchChange (ev: UniHelper.SwitchOnChangeEvent) {switchValue.value ev.detail.value
}
/scripttemplateviewswitch :valueswitchValue changeonSwitchChange //view
/template
总在这个例子中我们使用 ref 函数创建了一个名为 switchValue 的响应式引用并使用 :value 将 switchValue 的值传递给 switch 组件。我们还定义了一个名为 onSwitchChange 的函数它在开关状态发生变化时被 change 事件监听器调用从而根据事件对象中的 detail.value 更新 switchValue 的值。
加分-表单校验
项目中我们还通过 uni-forms 实现了表单的校验。
以下是使用 uni-forms 实现表单校验的具体步骤
创建表单数据和验证规则使用 ref 函数创建表单数据对象 form 和验证规则对象 rules。设置 ·uni-forms 属性在 uni-forms 组件上设置 :model 和 :rules 属性分别绑定到 form 和 rules。使用 uni-form-item 组件和 input 组件构建表单为每个表单项创建一个 uni-form-item 组件并设置 name 属性。在表单项内部使用 input 组件并使用 v-model 指令进行双向数据绑定。创建表单引用使用 ref 函数创建一个名为 formRef 的引用将其设置为 uni-forms 组件的 ref 属性。创建表单提交处理函数定义一个名为 onSubmit 的函数在此函数内部使用 formRef.value.validate() 方法进行表单验证。根据验证结果执行相应的逻辑例如提交表单或显示错误提示。添加提交按钮在模板中添加一个提交按钮为其设置 tap 事件监听器绑定到 onSubmit 函数。
script setup langts
import { ref } from vueconst form ref({username: ,password: ,
})const rules: UniHelper.UniFormsRules {username: {rules: [{ required: true, errorMessage: 用户名不能为空 }],},password: {rules: [{ required: true, errorMessage: 密码不能为空 }],},
}const formRef refUniHelper.UniFormsInstance()const onSubmit async () {try {const result await formRef.value?.validate!()console.log(校验通过提交数据, result)} catch (error) {console.log(校验未通过, error)}
}
/scripttemplateviewuni-forms :modelform :rulesrules refformRefuni-forms-item label用户名 nameusernameinput v-modelform.username placeholder请输入用户名 //uni-forms-itemuni-forms-item label密码: namepasswordinput password v-modelform.password placeholder请输入密码 //uni-forms-itemviewbutton taponSubmit提交/button/view/uni-forms/view
/template
参考链接
普通 form 表单
uni-forms 表单校验 类似问题 在 uni-app 中如何处理不同平台下的表单处理差异 问请谈谈你在使用 uni-app 过程中遇到的问题以及如何解决它们。
必答
总在遇到问题时我一般都是参考官方文档、社区资源和其他开发者的经验。
分根据自身理解选其中几点回答即可
vue 语法支持问题uni-app 在发布到 H5 时支持所有 vue 的语法发布到 App 和小程序时由于平台限制无法实现全部 vue 语法。相比 Web 平台 Vue.js 在 uni-app 中使用差异主要集中在两个方面 新增uni-app 除了支持 Vue 实例的组件生命周期还拥有应用生命周期及页面的生命周期。受限相比 Web 平台在小程序和 App 端部分功能支持不完善具体见兼容性列表。如微信小程序端不支持自定义指令 directive可通过封装工具函数实现参考方案。跨平台兼容性问题 由于 uni-app 需要适配多个平台开发过程中可能会遇到不同平台的兼容性问题。在遇到此类问题时可以参考官方文档和社区资源了解不同平台的特性和限制然后针对性地解决问题。如果必要可以使用条件编译在不同平台下执行不同的代码。 如 H5 端不支持 微信登录滚动驱动的动画等功能。性能问题 在 uni-app 开发过程中可能会遇到页面性能问题如加载速度慢等。为了解决这些问题可以尝试以下方法 减少本地图片资源压缩图片避免使用大图素材中已优化在线压图工具减少不必要的计算和渲染使用分包加载按需加载页面和资源插件兼容性问题 当使用第三方插件或库时可能会遇到兼容性问题。在这种情况下可以尝试以下方法 查找针对 uni-app 的插件版本(如 SKU 组件要筛选支持 Vue3 版的axios 不支持小程序端则自行封装)修改插件配置以适应 uni-app 的环境(如 Pinia 持久化存储方案需要改默认配置)寻找替代方案如使用 uni-app 官方提供的 API 或组件。如 组件库使用官方的 uni-ui更新和维护问题 随着项目的发展可能需要更新和维护代码。为了降低维护成本可以 保持代码的模块化和组件化一直都有保持遵循良好的编码规范一直都有保持编写文档记录项目结构和功能。一直都保持如封装函数写 JSDoc 注释
总其实 uni-app 官方文档记录了大量的跨平台兼容性问题和解决方案uni-app 插件市场有大量插件同时 uni-app 社区也有其他开发者分享的经验也可以在 uni-app 社区提问题以找到合适的解决方案。最后保持良好的编码规范和项目结构可以降低维护成本提高开发效率。
参考链接
uni-app H5 正常但小程序异常的可能性uni-app 区别于传统 web 开发的注意uni-app 跨端兼容uni-app 常见问题-官方整理uni-app 优化建议-官方整理uni-app 路由拦截方法使用智能 WebP, PNG 和 JPEG 压缩
问请简述代码规范在团队协作中的重要性
必答
总我们团队是使用 ESLint、Prettier 和 Husky 来确保代码质量和一致性
分根据自身理解选其中几点回答即可
保持代码一致性代码规范可以确保团队成员遵循相同的编码风格和约定。这可以提高代码的可读性使团队成员更容易理解和维护彼此的代码。提高代码质量通过强制执行一些最佳实践ESLint 可以帮助开发者避免常见的错误和潜在的风险。这有助于提高代码的质量减少维护成本。自动化格式化Prettier 可以自动格式化代码保持代码整洁减轻开发者在调整代码格式时的负担。它可以帮助开发者专注于编写功能代码而无需担心代码风格的问题。预提交检查Husky 可以在代码提交到版本控制系统如 Git之前执行一些预定义的任务如运行 ESLint 和 Prettier 检查。这有助于确保仅提交符合规范的代码从而减少代码审查和后期修复的成本。更好的协作通过遵循相同的代码规范和工具团队成员之间的协作变得更加顺畅。这有助于提高开发效率降低沟通成本。提高开发效率使用这些工具可以自动处理一些繁琐的任务如格式化、检查错误等从而使开发者可以专注于编写高质量的功能代码提高开发效率。
总总之通过遵循统一的规范团队可以更高效地开发和维护项目。
深入
可以谈谈在 uni-app 项目中是如何应用 ESLint、Prettier 和 Husky 的以及你遇到的一些挑战和解决方法。
总这些配置是由团队负责人制定当然也可以由你自己配置在小兔鲜儿的项目中已全部配置。
分具体步骤可以如下
首先我们需要安装 ESLint、Prettier 和 Husky 作为项目的开发依赖。接下来配置 ESLint。在项目根目录下创建一个 .eslintrc.js 或 .eslintrc.json 配置文件并定义相应的规则。可以根据项目需求选择使用 Vue 官方推荐的规则或者自定义规则。同时我们需要在项目的 package.json 文件中的 scripts 部分添加一个用于执行 ESLint 检查的脚本例如lint: eslint --ext .js,.vue,.ts --fix。接着配置 Prettier。创建一个 .prettierrc.js 或 .prettierrc.json 配置文件在其中定义代码格式化规则。同时可以在 .eslintrc.js 或 .eslintrc.json 文件中添加一些与 Prettier 相关的配置以确保 ESLint 与 Prettier 能够协同工作。然后配置 Husky。在项目中定义 Git 钩子。例如在 pre-commit 钩子中执行 ESLint 和 Prettier 检查以确保提交的代码符合规范。最后为了确保团队成员能够在各种编辑器中保持一致的代码风格建议在项目中添加一个 .editorconfig 文件定义编辑器相关的通用配置。
在应用这些工具时其实也遇到了的一些挑战
在使用 uni. 全局变量的时候报错针对 uni-app 项目设置全局变量如getCurrentPages、uni、wx、UniHelper。ESLint、Prettier 和编辑器之间可能存在冲突。为了解决这个问题可以在 .eslintrc.js 或 .eslintrc.json 文件中添加与 Prettier 相关的配置并确保编辑器插件正确地应用了这些配置。部分 ESLint 规则可能与项目需求不符。在这种情况下可以根据项目实际情况自定义规则或禁用部分不适用的规则。当使用第三方库或组件时可能会遇到与 ESLint 规则冲突的问题。可以在 .eslintignore 文件中排除这些文件或者在特定文件中禁用特定规则。
通过克服这些挑战我们可以在 uni-app 项目中顺利地应用 ESLint、Prettier 和 Husky确保代码质量和团队协作的高效性。
参考配置 /* eslint-env node */
require(rushstack/eslint-patch/modern-module-resolution)module.exports {root: true,extends: [plugin:vue/vue3-essential,eslint:recommended,vue/eslint-config-typescript,vue/eslint-config-prettier, // 遇到的挑战2: ESLint、Prettier 存在冲突],// 遇到的挑战1: 小程序全局变量globals: {uni: true,wx: true,WechatMiniprogram: true,getCurrentPages: true,UniApp: true,UniHelper: true,},parserOptions: {ecmaVersion: latest,},rules: {// 遇到的挑战2: ESLint、Prettier 存在冲突prettier/prettier: [warn,{singleQuote: true,semi: false,printWidth: 100,trailingComma: all,endOfLine: auto,},],// 遇到的挑战3: 部分 ESLint 规则与项目需求不符vue/multi-word-component-names: [off],vue/no-setup-props-destructure: [off],vue/no-deprecated-html-element-is: [off],typescript-eslint/no-unused-vars: [off],},
}
问请介绍 uni-app 中的条件编译和平台差异化处理?
必答
(总)在 uni-app 开发过程中由于需要适配多个平台可能会遇到不同平台之间的差异和兼容性问题。为了解决这些问题uni-app 提供了条件编译和平台差异化处理功能。
(分)
条件编译(常见)条件编译是在编译阶段根据预设条件对代码进行不同分支的编译。在 uni-app 中可以通过条件编译实现针对不同平台编译不同的代码。 通过在代码中添加特定的注释来实现条件编译。例如
// #ifdef H5
console.log(这段代码只编译到H5端)
// #endif// #ifdef MP-WEIXIN
console.log(这段代码只编译到微信小程序端)
// #endif
平台差异化处理 平台差异化处理是在运行时根据当前平台执行不同的代码逻辑。在 uni-app 中可以通过 const { osName } uni.getSystemInfoSync() 来判断当前平台然后编写针对不同平台的代码逻辑。例如
// 获取系统名称
const { osName } uni.getSystemInfoSync()
if (osName ios) {console.log(ios平台执行的逻辑)
} else if (osName android) {console.log(android平台执行的逻辑)
}
总结 条件编译和平台差异化处理是 uni-app 为解决多平台兼容性问题提供的两种方法。条件编译更加常见在编译阶段根据预设条件对代码进行不同分支的编译而平台差异化处理是在运行时根据当前平台执行不同的代码逻辑。根据项目需求和场景可以灵活选择使用这两种方法。
加分
条件编译在 uni-app 中有很多应用场景主要用于处理不同平台间的差异和兼容性问题。以下是一些常见的应用场景
登录功能差异不同平台可能有不同的登录方式和 API。例如微信小程序可以使用微信登录而 H5 平台可能需要使用其他登录方式如手机号验证码。这种情况下可以使用条件编译为不同平台提供适当的登录实现。
// #ifdef MP-WEIXIN
// 微信小程序登录
const { code } wx.login()
// #endif// #ifdef H5
// H5平台登录如手机号验证码
// ...
// #endif
API 差异不同平台可能存在 API 差异有的 API 在某些平台上可能不可用。在这种情况下可以使用条件编译来处理平台差异。
// #ifdef H5
navigator.geolocation.getCurrentPosition((position) {// H5获取地理位置
})
// #endif// #ifdef MP-WEIXIN
wx.getLocation({type: wgs84,success(res) {// 微信小程序获取地理位置},
})
// #endif
UI 组件差异不同平台的 UI 组件可能存在差异例如 导航栏、底部标签栏微信小程序的picker组件和 H5 平台的select元素。可以使用条件编译针对不同平台提供不同的 UI 组件。 template!-- #ifdef H5 --selectoption valueoption1Option 1/optionoption valueoption2Option 2/option/select!-- #endif --!-- #ifdef MP-WEIXIN --pickerviewOption 1/viewviewOption 2/view/picker!-- #endif --
/template 资源路径差异有时不同平台对资源路径的处理方式不同可以使用条件编译为不同平台提供适当的资源路径。
template!-- #ifdef H5 --img data-fancyboxgallery src/static/img/logo.png /!-- #endif --!-- #ifdef MP-WEIXIN --image src/static/img/logo-weixin.png /!-- #endif --
/template
总之条件编译在 uni-app 开发过程中具有广泛的应用场景主要用于解决不同平台间的差异和兼容性问题。根据具体需求可以灵活运用条件编译来实现适配不同平台的功能和表现。 类似问题 问如何在 uni-app 的组件中实现跨平台逻辑 问如果区分 ios 端和 android 端执行不同的业务