ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

uni-app微信小程序登录页开发:视觉细节与登录状态机闭环

uni-app微信小程序登录页开发:视觉细节与登录状态机闭环 1. 从标题说开这个登录页到底要解决什么问题做 uni-app 微信小程序的这几年我发现一个挺有意思的现象技术群里问得最多的往往不是复杂业务逻辑而是登录页怎么做才好看。这看起来是个小问题但真动手写过的都知道登录页是整个小程序里性价比最低又最难讨好的一个页面——它逻辑不复杂却要在几十行代码里同时扛住视觉、交互、性能、适配四件事。这一篇是好看的 ui 登录页面系列的第四篇前三篇把基础骨架、渐变背景、表单结构都过了一遍这篇我打算把重点放在视觉细节的参数化落地和登录链路的完整闭环上也就是把看起来好看变成每一处都能说出为什么这么写。先明确这篇的读者定位。如果你已经在用 uni-app 开发微信小程序写过至少一个能跑起来的项目那这篇基本可以当作模板直接抄如果你刚接触 uni-app只看过官方文档里的 hello world那也能看懂只不过我建议你先搭一个空白页面边看边敲纯看文字很容易漏掉细节。我自己的习惯是任何一篇讲 UI 的文章如果不配可运行的代码基本等于没说所以下面每一段关键的视觉参数和逻辑我都会给出可以直接粘贴进.vue文件的代码。1.1 登录页在整个小程序里的真实分量很多人把登录页当成入口那一关过了就丢到脑后这个认知其实挺吃亏的。登录页是小程序里用户停留时间最短、但触发网络请求最密集的页面之一一次手机号输入、一次验证码发送、一次协议勾选、一次提交登录每个动作背后都是状态变化。如果这个页面的状态管理写得乱后面所有需要登录态的页面都会跟着遭殃——token 拿不到、用户信息是空的、退出登录后缓存没清干净这些都是从登录页埋下的雷。更现实一点说登录页还是审核和体验的第一印象。微信小程序审核对登录流程的合规性有一定关注度比如是否强制授权、是否默认勾选协议、是否有明确的用户知情提示。视觉上做得干净利落体验上少一次多余的点击用户流失率就能降下来。我做过一个对比同一个项目把登录页从手机号 密码 图形码三件套换成手机号 短信验证码注册转化在那次改动后提升了不少原因很简单用户忘密码的成本太高了。所以这篇的定位不是教你画一个漂亮的界面而是把登录页当作一个小型状态机来设计视觉是外壳状态流转是内核两者要一起考虑。标题里说的好看我理解成三层意思——配色舒服、层级清晰、动效不跳戏缺一个都会显得廉价。1.2 技术栈与版本前提先把环境说清楚避免你照着抄却跑不起来。这套页面的基础组合是uni-app Vue3 组合式 API script setup 语法糖编译器版本建议在 3.0 以上微信开发者工具的基础库选择 2.30 以上比较稳妥。为什么强调 Vue3因为组合式 API 在登录页这种状态比较多但又不复杂的场景里优势很明显逻辑可以按功能拆成几个独立的 ref 和 computed不用像选项式那样在 data、methods、computed 之间来回跳。HBuilderX 新建项目的时候直接选uni-app 项目 → 默认模板 → Vue3或者用 CLI 创建也可以。要注意一个坑Vue3 项目的v-model在小程序端对自定义组件的支持和 H5 端不完全一致如果后面你要抽一个自己的输入框组件事件名得用update:modelValue别用老写法。这个细节我在第二篇里提过一次但每年都有新人踩还是再强调一下。另外微信小程序的原生登录 API 是uni.login它返回的code只能用来换 openid 和 session_key不要拿它当业务 token 用。这句话我在后面第四章还会再拆开讲因为这是新手最容易搞混的地方。1.3 页面结构分层思路我写登录页习惯先分层再写代码一共分四层最底下是背景层负责渐变或者装饰性图形往上是卡片层承载所有表单元素再往上是交互层也就是输入框、按钮、协议勾选这些可点击的东西最上面是反馈层包括 toast、loading、错误提示。分层的好处是之后无论改背景还是改按钮动效你都知道该动哪一块不会牵一发动全身。用模板结构表达出来大概是这样template view classlogin-page !-- 背景层 -- view classbg-layer view classblob blob-1/view view classblob blob-2/view /view !-- 卡片层 -- view classcard view classheader.../view !-- 交互层 -- view classform.../view /view !-- 反馈层由 uni.showToast 等承担 -- /view /template这套分层看起来有点为了分层而分层但它解决了一个真实问题绝对定位元素的层级冲突。背景的装饰圆、卡片的阴影、输入框的聚焦边框如果不按层管理 z-index很容易出现输入框被背景盖住、或者阴影压到按钮上的情况。我吃过一次亏背景光斑的 z-index 写高了结果整个表单点不动排查了半小时才发现是层级问题从那以后就固定按这四层来写。2. 视觉层拆解配色、层次与高级感的来源高级感这个词很虚但拆开看其实是可以量化的低饱和度、克制的渐变、统一的圆角系统、有呼吸感的留白再加上一两个点睛的动效。这一章我把这几件事逐个参数化你照着调数值就能得到差不多的效果。2.1 配色方案与渐变背景的具体写法先说配色。登录页最忌讳两种极端一是纯白背景配纯黑字像文档二是搞一堆高饱和渐变色像十年前的 PPT。我的经验是主色用品牌色但饱和度压到 60%~70%背景用主色的极浅色做渐变文字用深灰而不是纯黑。举个具体的如果品牌主色是#4A7CFF那背景可以做成从#EEF3FF到#F8FAFF的斜向渐变文字用#1A1D26辅助文字用#8A8F99。背景的装饰光斑我用的是大半径圆形加高斯模糊参数上有个细节模糊值要和圆的大小成比例不然小圆模糊过度会糊成一团大圆模糊不够会露出生硬的边。我一般用圆直径的 25% 左右作模糊值。.bg-layer { position: fixed; inset: 0; z-index: 0; background: linear-gradient(135deg, #EEF3FF 0%, #F8FAFF 60%, #F3F0FF 100%); overflow: hidden; } .blob { position: absolute; border-radius: 50%; filter: blur(60rpx); opacity: 0.55; } .blob-1 { width: 420rpx; height: 420rpx; background: #9BB6FF; top: -120rpx; right: -100rpx; } .blob-2 { width: 320rpx; height: 320rpx; background: #C6B8FF; bottom: -80rpx; left: -60rpx; }注意filter: blur()在微信小程序里的性能开销比 H5 大尤其是圆特别大的时候。如果你发现低端安卓机上滑动掉帧可以改成用radial-gradient直接做柔边视觉差异很小但性能好很多。这里有个小技巧值得单独说光斑不要放在表单正后方。它会影响输入框文字的可读性虽然看着柔和但用户盯久了会觉得累。我的做法是把光斑推到屏幕对角线的两个角上中间留出干净区域给卡片。2.2 卡片质感圆角、阴影、描边的三角平衡卡片是登录页的视觉中心它的高级感基本由三个参数决定圆角、阴影、描边。很多新手只调阴影调出来总是灰蒙蒙的问题就出在阴影颜色的选择上。纯黑阴影rgba(0,0,0,.2)在浅色背景上会显脏正确做法是用主色的深色版本透明度压到 8% 左右。我的常用参数是圆角32rpx阴影0 12rpx 40rpx rgba(74,124,255,0.10)再叠一层0 2rpx 8rpx rgba(26,29,38,0.04)做贴地感。为什么叠两层因为单层大模糊阴影负责悬浮单层小模糊阴影负责贴地两者叠加的立体感比单纯调大 blur 要真实得多这是从设计规范里学来的思路。.card { position: relative; z-index: 1; margin: 160rpx 48rpx 0; padding: 64rpx 48rpx 56rpx; background: rgba(255, 255, 255, 0.92); border-radius: 32rpx; box-shadow: 0 12rpx 40rpx rgba(74, 124, 255, 0.10), 0 2rpx 8rpx rgba(26, 29, 38, 0.04); backdrop-filter: blur(20rpx); }backdrop-filter在小程序里的支持度参差不齐我一般会在它后面补一个不透明的background兜底这样即使毛玻璃失效卡片也是完整可见的。别小看这个兜底我用的是老款安卓测试机毛玻璃直接不生效如果没有兜底整个卡片会变成半透明灰非常难看。圆角这块还有一个容易忽略的点卡片圆角和内部输入框圆角要有比例关系。我习惯卡片 32rpx、输入框 20rpx、按钮 20rpx形成 1.6 倍左右的层级差。如果三个都写 32rpx界面会显得很钝缺少层次。2.3 微动效按钮态、输入聚焦、加载过渡动效是区分模板和作品的分界线但登录页的动效必须克制一个页面塞三种以上的动画就会显得吵。我一般只留三处按钮按下反馈、输入框聚焦时边框和图标变色、提交时的加载旋转。按钮反馈用 CSS:active就够了缩放 0.97 加透明度 0.9比写 JS 监听 touchstart 省事得多。聚焦态要小心小程序里 input 的 focus 事件在小键盘弹起时可能触发多次所以状态改变要用一个布尔值加判断而不是直接 toggleconst focusedField ref() function onFocus(field) { focusedField.value field } function onBlur() { focusedField.value }这样写的好处是无论 focus 事件触发几次状态都是幂等的不会出现聚焦了两次反而取消聚焦的诡异现象。这个坑我在第三篇里踩过当时以为是组件库的 bug查了半天源码才发现是自己状态写错了。加载过渡我推荐用按钮内部的小圆环旋转而不是全屏 loading。原因是全屏 loading 会遮住整个页面用户看不到自己填了什么心理上会觉得卡住了。按钮内联 loading 则传递出一个明确的信号——你的操作正在处理体验上从容很多。button classsubmit-btn :disabledloading :loadingloading clickhandleSubmit {{ loading ? 登录中 : 登 录 }} /button微信小程序原生 button 的loading属性会自带一个转圈图标省得自己画。但它有个限制默认 loading 图标是白色的如果你的按钮是浅色背景就看不见了。所以要么按钮用深色要么自己写一个 view 来模拟我一般选前者简单可靠。3. 交互与逻辑把表单做得既好看又好用界面好看只是第一步真正决定用户会不会骂你的是填表单的过程顺不顺手。这一章聊的全是细节活每一条都来自实际项目里被投诉过的点。3.1 输入框的状态管理与即时反馈输入框要管的状态其实有四种默认、聚焦、已填写、错误。很多人只写默认和聚焦两种结果用户填完内容后没有任何视觉确认会下意识怀疑到底输进去了吗。我的做法是已填写状态下给一个极淡的主色背景错误状态下边框变红并在下方显示提示文案。手机上输入时最容易出问题的是清空按钮的显隐。什么时候显示那个小叉我的判断条件是当前字段有值且处于聚焦状态两个条件同时满足才显示。如果只有值就显示用户在滚动页面时满屏都是小叉很乱如果只有聚焦就显示会有个空叉子点了也没反应更莫名其妙。view classfield :class{ is-focus: focusedField phone } input v-modelform.phone typenumber maxlength11 placeholder请输入手机号 placeholder-classph focusonFocus(phone) bluronBlur / view v-ifform.phone focusedField phone classclear-btn clickform.phone ×/view /view这里的placeholder-class值得说一下。小程序里 placeholder 的样式在部分机型上优先级很高直接写 CSS 选择器可能覆盖不掉必须用placeholder-class指定一个类名才行。这个细节官方文档里有但很多人翻不到导致 placeholder 颜色一直改不了。3.2 表单校验策略什么时候校验比怎么校验更重要校验这件事时机比规则重要得多。最常见的错误写法是每次输入都校验一次用户刚输第一个数字就弹手机号格式不正确体验极差。我用的策略是分三级输入过程中只做长度限制maxlength不做格式校验失焦时做一次格式校验错误就提示提交时做全量校验第一个错误字段滚动到可视区域并聚焦。这套策略的核心逻辑是不打断用户输入。用户打字的时候思路是连贯的你在中间插一个红字提示他下次输入就会犹豫。等到他手指离开输入框说明这一段输入完成了这时候提示才有意义。手机号的校验规则我用的是/^1[3-9]\d{9}$/验证码用/^\d{6}$/。这两个正则看起来简单但有个细节不要用\d{11}直接匹配所有数字因为 12 开头的号码段是不存在的用户输错了你还放行最后在服务端才报错白跑一趟网络请求。前端能挡掉的错误就挡掉是登录页的基本素养。3.3 按钮加载态与防重复提交的两道保险防重复提交这件事我见过太多项目只做了一半。UI 层面按钮置灰是最基础的但手指点击的速度可能快于状态更新的速度也就是说用户在loading变成 true 之前已经点了第二下。第一道保险是:disabledloading第二道保险必须在 JS 里const loading ref(false) async function handleSubmit() { if (loading.value) return // 第二道保险 if (!validateAll()) return loading.value true try { await doLogin() } finally { loading.value false // 无论成功失败都复位 } }finally这一行特别重要。如果登录接口报错你的loading卡在 true用户会发现按钮永远点不动只能退出重进。我统计过一次线上反馈相当一部分小程序卡死其实是 loading 没复位导致的跟性能没关系。3.4 协议勾选的合规与交互细节登录页底部的用户协议与隐私政策勾选是合规要求也是体验细节。我的处理原则有三条默认不勾选、点击整行都能切换、文案里的协议名用主色且可点击跳转。默认不勾选这条现在已经是硬性常识了但很多人还是习惯写checked: true这在审核时是有风险的。点击区域这块一定要把 checkbox 和文案包在同一个可点容器里只让那个小方块能点的话手指准确的命中率其实不高用户会反复点几次才成功。至于文案跳转用click.stop阻止冒泡避免点协议名的时候顺带把勾选也切换了。view classagreement clickagreed !agreed view classcheckbox :class{ checked: agreed }/view text classtext我已阅读并同意/text text classlink click.stopopenProtocol(user)《用户协议》/text text classtext和/text text classlink click.stopopenProtocol(privacy)《隐私政策》/text /view实操心得checkbox 的勾选对勾不建议用特殊字体图标直接用 CSS 边框旋转 45 度画一个勾最稳跨端表现一致也不依赖字体文件加载。4. 登录链路的完整落地视觉和交互都到位之后就是真正的数据流了。这一章是整篇的硬核部分也是很多教程一带而过的地方。4.1 code 换 session 与业务 token 的正确分工微信小程序的登录流程经常被讲混我用一句话概括uni.login拿到的是入场券它换来的 session 是临时身份真正在业务里横着走的是你自己服务端签发的 token。这三者不能互相替代。完整链路是这样的用户点登录按钮前端调用uni.login拿到code把code连同手机号、验证码一起发给自己的服务端服务端拿code去微信的接口换openid和session_key然后生成自己的业务 token 返回前端把 token 存起来后续所有请求带上它。async function doLogin() { const { code } await new Promise((resolve, reject) { uni.login({ provider: weixin, success: resolve, fail: reject }) }) const res await uni.request({ url: ${BASE_URL}/auth/login, method: POST, data: { code, phone: form.phone, smsCode: form.smsCode } }) if (res.data.code ! 0) { throw new Error(res.data.message || 登录失败) } uni.setStorageSync(token, res.data.data.token) uni.setStorageSync(userInfo, res.data.data.userInfo) uni.reLaunch({ url: /pages/index/index }) }这里有个关键点code是一次性的用完即失效。如果你的接口报错需要用户重试必须重新调一次uni.login拿新的 code不能复用旧的。我遇到过一次线上问题用户第一次登录失败后重试总是失败排查了两小时才发现是 code 被复用了改成每次提交都重新获取就正常了。4.2 token 存储与请求拦截token 存哪里uni.setStorageSync存在本地简单直接但要注意它是明文存储的。小程序环境相对封闭风险可控但我不建议把敏感信息一起存进去。我一般只存 token 和必要的用户基础信息像身份证号、完整手机号这类需要时再单独请求。请求拦截这块如果项目里用了uni.request的封装或者第三方请求库记得在请求头里统一注入 token并且处理401 的场景——token 过期时清空本地存储并跳回登录页而不是让用户在所有页面里看到一堆报错。uni.addInterceptor(request, { invoke(args) { const token uni.getStorageSync(token) if (token) { args.header { ...args.header, Authorization: Bearer ${token} } } }, success(res) { if (res.statusCode 401) { uni.removeStorageSync(token) uni.reLaunch({ url: /pages/login/login }) } } })注意拦截器里跳转登录页前最好判断一下当前页面是不是已经是登录页否则极端情况下会出现重复跳转的堆栈异常。4.3 图形验证码与短信验证码的接入姿势验证码分两种短信验证码是发给手机号的一次性数字图形验证码是人眼识别的字符或滑块。前者用于登录验证后者通常用于防止短信接口被刷。实际项目里常见的是两者配合点发送验证码之前先弹一个图形验证码验证通过才真的发短信。前端接入图形验证码的流程是页面加载时请求一次验证码图片服务端返回图片和对应的标识 key用户输入后连同 key 一起提交验证。这里要处理两个细节验证码过期要能刷新所以图片上加一个点击刷新的事件提交失败后验证码一般会失效需要自动刷新一次否则用户拿着旧图反复输都过不了。view classcaptcha-row v-ifneedCaptcha input v-modelform.captcha placeholder请输入图形验证码 / image :srccaptchaImg clickrefreshCaptcha classcaptcha-img / /view发送短信的按钮要有 60 秒倒计时而且倒计时状态要能在页面隐藏再回来之后恢复正确。简单用一个setInterval在onUnload里清理就够了但如果用户中途切到后台小程序的定时器可能被挂起回来时倒计时对不上。更稳的做法是记录一个结束时间戳每次渲染时用当前时间减去它算剩余秒数这样切后台再回来也不会错乱。顺便提一句验证码校验一定放在服务端做前端的所有校验都只是提升体验不能当作安全手段。这个原则适用于所有登录相关的场景我在代码评审里看到过前端直接判断验证码等于某个固定值的写法那是绝对不行的。5. 适配与避坑多端差异的真实表现uni-app 最大的价值是跨端最大的坑也是跨端。登录页作为纯 UI 页面看起来应该很好统一实际上微信小程序端和 H5 端、App 端的差异还是会冒出来。这一章我按实际踩过的顺序讲。5.1 rpx 与 px 混用的边界在哪里rpx是小程序的响应式单位标准是 750rpx 等于屏幕宽度。用它写尺寸在不同机型上会自动等比缩放这很好但不是所有地方都该用 rpx。我的经验是字号、间距、圆角、图标大小用 rpx1px 的细线、阴影的偏移量和模糊值用 px。为什么细线要用 px因为如果用 rpx在 2 倍屏上 1rpx 换算出来是 1px 的物理像素看起来会粗细不均。阴影同理用 rpx 写模糊值在低分辨率设备上会糊得不成样子。至于字号有个下限要注意24rpx在小屏手机上已经接近看不清了正文建议不低于26rpx。还有一个容易忽略的地方卡片宽度不要写死690rpx。虽然 750 减去左右各 30 的边距确实是 690但用户在平板上打开时整个卡片会被拉伸得特别宽阅读体验很差。可以给卡片加一个max-width在宽屏上居中显示观感会好很多。5.2 键盘弹起与安全区的处理键盘弹起导致的页面错位是登录页最经典的坑。微信小程序的 input 有adjust-position属性默认是 true也就是键盘弹起时页面会自动上推。多数情况下这个默认行为就够了但如果你的登录卡片是垂直居中的上推之后卡片会被顶出屏幕顶部内容看不见。我的方案是把卡片改成顶部对齐加固定上边距而不是垂直居中。虽然视觉上稍微没那么完美居中但键盘弹起时不会有任何跳动用户视野稳定。如果你坚持居中那就得监听focus时手动调整 margin代码量翻倍还不稳定不划算。安全区的问题主要出现在全面屏底部。底部的协议文案如果贴着屏幕最下方在带虚拟指示条的机型上会被挡住。用padding-bottom: env(safe-area-inset-bottom)可以解决但要注意 uni-app 编译到小程序时这个 CSS 变量在部分基础库版本上不生效稳妥起见我会额外加一个固定值的兜底 padding。.login-page { padding-bottom: calc(40rpx env(safe-area-inset-bottom)); padding-bottom: calc(40rpx constant(safe-area-inset-bottom)); /* 老版本兜底 */ }5.3 微信小程序端特有的几个注意点有几个差异只在微信小程序端出现H5 上完全正常很容易被忽略。第一个是页面栈限制。小程序的页面栈最多十层登录成功后如果用navigateTo跳首页用户按返回键会回到登录页这个体验是错的。所以登录成功后必须用reLaunch或者redirectTo把登录页从栈里清掉。这一点我在第四章的代码里已经体现出来了。第二个是输入框的原生层级问题。微信小程序的 input 在早期版本里是原生组件层级最高会盖住所有普通 view。虽然现在的新版基础库已经改善了很多但如果你在输入框上方做浮层还是要留意。我遇到过弹窗被输入框盖住的情况最后的解决方案是用cover-view或者干脆把弹窗位置挪开。第三个是基础库版本差异。有些新属性在老版本基础库上不生效比如backdrop-filter。稳妥的做法是功能降级能用则用不能用也不影响主体功能。可以在小程序后台设置最低基础库版本但设置得太高会流失一部分老设备用户这个权衡得看你的用户画像。6. 性能优化与常见问题速查6.1 首屏渲染与资源体积控制登录页通常是用户进入小程序后看到的第一个页面它的首屏速度直接影响留存。这块我做了三件事背景用纯 CSS 画不用图片、图标用字体或者 SVG 内联不用 PNG、首屏不加载任何非必要的 JS。用 CSS 画背景的好处前面说过性能好而且没有网络请求。图标这块如果项目里已经用了图标字体直接复用如果没有小图标建议内联 SVG 或者用 CSS 画一个 PNG 图标动辄几 KB七八个就是几十 KB在弱网环境下就是几秒的差距。至于 JS登录页不需要引入状态管理库的全量代码按需引入或者干脆不用一个页面的局部状态用ref管就够了。还有一个小优化点输入框的type属性要写对。手机号写typenumber验证码也写typenumber这样键盘会自动弹出数字键盘用户少切一次键盘体验和速度都提升了。密码字段如果要显示/隐藏切换用:password属性控制而不是切换 type后者在部分机型上会导致光标位置重置。6.2 输入卡顿的排查思路输入框打字卡顿是高频反馈但原因往往不在输入框本身。我按可能性从高到低列一下排查顺序排查项典型现象处理方式输入事件里有重计算每打一个字就卡一下用防抖或者把校验移到失焦大范围动态样式绑定滚动或输入时整体掉帧减少响应式依赖的节点数量背景模糊滤镜低端机持续掉帧改用渐变模拟或降低模糊半径页面元素过多首屏和输入都卡精简 DOM隐藏元素用 v-if长列表在同一个页面输入时页面重排拆分成独立页面或虚拟列表我遇到最多的是第一项。有人写了个watch监听输入内容每次变化都去请求接口查手机号是否存在结果每按一个键就发一次请求别说卡顿流量都浪费了。这种需求应该改成失焦后再查或者加 500 毫秒防抖。6.3 常见问题速查表下面这张表是我攒了三年的登录页翻车记录基本覆盖了你能遇到的大部分情况问题原因解决方案点击登录没反应loading 未复位或事件未绑定加 finally 复位检查 click提示登录失败但无详情错误信息被吞统一错误处理打印服务端 message第二次登录必失败code 被复用每次提交重新调 uni.login退出登录后仍显示用户信息缓存未清理退出时清空所有 storage 并 reLaunch输入框 placeholder 颜色改不了未使用 placeholder-class加 placeholder-class 属性安卓机上面包屑被键盘遮挡页面垂直居中改为顶部对齐布局iOS 上点击有延迟未使用 :active 或用了 touch用 CSS 伪类替代 JS 事件验证码按钮倒计时错乱定时器切后台被挂起改用时间戳计算剩余秒数卡片在不同机型宽度不一写死宽度用百分比加 max-width深色模式下界面发白未适配深色模式用 CSS 变量或 media 查询这张表里我最想强调的还是第一条和第三条因为它们最隐蔽排查起来最费时间。尤其是 code 复用那个问题现象是偶尔失败很容易被当成网络问题放过去实际上它必然会发生只是频率不高。7. 我在实际项目里踩出来的几条经验写了这么多技术细节最后聊几条不那么技术、但同等重要的经验。第一条是别在登录页堆功能。我见过一个项目登录页上塞了手机号密码登录、微信一键登录、账号密码、游客体验四种方式还带一个轮播的活动 banner。结果页面长得吓人用户第一眼不知道点哪个。登录页的核心任务只有一个让用户用最快的方式进来。如果真的需要多种方式也应该是主次分明一种主推、其余藏在更多方式里。第二条是把错误提示写清楚。登录失败这四个字等于没说用户不知道是自己手机号错了还是验证码过期了还是网络断了。我现在养成的习惯是服务端返回的message尽量直接展示给用户实在不适合展示的再兜底一个通用文案。用户骂人的次数会明显减少。第三条是登录页要能自己一个人测试。什么意思呢就是不要让它强依赖某个只有正式环境才有的接口。我会在开发阶段用 mock 数据把整个链路跑通包括成功、验证码错误、网络超时三种情况确保每种情况下的 UI 表现都正常。等接真接口的时候只需要替换请求层页面代码一行都不用改。第四条关于设计走查。功能做完之后我习惯拿三台设备过一遍一台小屏安卓、一台常规尺寸 iPhone、一台平板或者折叠屏。这三个尺寸基本能覆盖所有布局问题。特别是折叠屏展开之后屏幕很宽如果你的卡片没有 max-width视觉效果会非常奇怪这个在正常手机上完全看不出来。这套登录页的代码我前后迭代了四次从最初的能跑就行到现在的细节打磨每次都是在真实用户的反馈里改出来的。视觉上的好看其实是最容易的部分照着参数调就能出效果难的是那些看不见的地方比如状态复位、错误处理、跨端差异。把这两者都做扎实了一个登录页才算真的完成。后续如果你要在这个基础上继续扩展我的建议是往无密码登录的方向走用手机号加短信验证码或者第三方授权替代密码输入能再砍掉一整个输入框和相关的状态管理用户的操作路径会短很多维护成本也跟着降下来。
返回列表