【uni-app】uni-app移动端开发 - 登录界面
基本需求uni-app 框架的优点在于一次编码,多端编译运行。本次通过完成一个登录界面,来学会uni-app 框架的使用,以及开发过程需要注意的点,还有难以排查出来且又找不到资料的一些坑,总有一些你需要的信息,接下来先明确登录界面的基本需求。登录界面是再简单不过的界面,但麻雀虽小,五脏俱全。本次演示在用户输入框、密码输入框及一个登录按钮的基础上,增加些许样式,完善交互中容易被忽视的问题。操作流程:
基本需求
uni-app 框架的优点在于一次编码,多端编译运行。本次通过完成一个登录界面,来学会 uni-app 框架的使用,以及开发过程需要注意的点,还有难以排查出来且又找不到资料的一些坑,总有一些你需要的信息,接下来先明确登录界面的基本需求。
登录界面是再简单不过的界面,但麻雀虽小,五脏俱全。本次演示在用户输入框、密码输入框及一个登录按钮的基础上,增加些许样式,完善交互中容易被忽视的问题。
操作流程:点击 帐号输入框 并输入 -> 点击 密码输入框 并输入 -> 登录按钮 变为可用并亮起 -> 点击登录按钮,最终完成效果图如下:
项目地址及运行方法
Git 项目地址为:https://github.com/Jokerlsss/uni_app_login
下载后解压,直接导入到 HX 中即可运行
交互注意点
- 弹起键盘时,整体界面往上移动,在 不生成滚动条 的同时,也 不能遮盖住控件。
- 点击登录按钮后,需要有一个登录中 loading 反馈;登录成功后,使用 toast 弹窗提示后跳转。
- 聚焦输入框时应有合适的动画样式变化,让用户能够知道当前所处的输入框焦点在哪里。
- 清除内容后需要重新将 焦点聚焦 到对应的 input 框上。
- 登录按钮在禁用时,颜色变淡。
- 登录页面 禁止下拉刷新 。
实现准备
1. UI 库的选择
在使用 uni-app 之前,我以为 vant、Mint 等移动端 UI 库可以进行兼容,但在真正导入和使用后,发现兼容性并不那么好,也可能是我的引用方式不妥。经过一阵子的摸爬滚打后,比较推荐的 uni-app 有两个 UI 库,一个是原生的 uni-ui 库,一个是 DCloud 市场(也就是 HBuilderX 编译器中的插件市场)中的 uView-ui。这两个对于 uni-app 几乎是量身定制,推荐使用,也可两者结合使用,使用方法后续会提到。
uni-ui
在使用 HBuilderX 新建项目时,选择 uni-app 中的默认模板新建即可,在代码编写过程中打出 u 的时候,便会提示如 uInput 的联想,这便是 uni-ui 的组件,直接使用即可,具体使用方法参考官方文档。
uView-ui
uView官方文档。我这边的方式是采用 npm 的方式进行安装,如下(在此之前,先在 HBuilderX 的插件市场中安装内置终端,然后再在终端中执行如下操作):
① 安装 uview-ui
// 如果项目中没有 package.json 文件时,先执行如下命令:
npm init -y
// 安装
npm install uview-ui
// 更新
npm update uview-ui
② 安装 scss
如果是通过 HX(HBuilderX 的简称,下文同)创建的项目,则进入到 插件市场 搜索 Scss/Sass 编译插件进行安装,安装后重启 HX 即可。
如果是通过 vue-cli 创建的项目,则通过 npm 的方式进行安装,这里不再赘述,详见 uview-ui 文档。
③ 配置
1)在根目录的 main.js 中引入 uView js 库
// main.js
// 这两行代码应放在 import Vue ... 之后
import uView from "uview-ui";
Vue.use(uView);
2)在 uni.scss 中引入 uView 的全局Scss文件
/* uni.scss */
@import 'uview-ui/theme.scss'
3)引入 uView 基础样式
注意:以下这行代码应在 App.vue 中 style 的 首行 位置引入,注意加上 lang = "scss" 属性
<style lang="scss">
/* 要写在第一行 */
@import "uview-ui/index.scss"
</style>
4)配置 easycom 按需引入组件模式
配置完后,重启 HX 并重新编译才能正常使用,且在 pages.json 文件中只能有一个 easycom 字段。
之后在页面使用的时候,无需 import 注册组件就可以直接使用。
// pages.json
{
"easycom": {
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
},
// 此为本身已有的内容
"pages": [
// ......
]
}
2. 代码编辑器
因为 uni-app 和 HBuilderX 是同一个团队出的,那么首选是 HBuilderX,在里面可以安装一些插件,如 Sass,甚至可以安装一些别人封装好的组件进行学习、使用。
主要功能及实现
围绕我们的需求,来对这些基本的交互一一进行实现。
① 弹起键盘时,整体界面往上移动,在 不生成滚动条 的同时,也 不能遮盖住控件。
1)问题描述
移动端在点击 input 框时会弹起键盘,键盘会有一定的高度,如果我们整体的控件高度设置不当的话,可能会出现 键盘把某些控件遮挡住,导致体验不佳,或者导致 页面出现滚动条,用户体验感觉软件排版不严谨。
2)思路
由于移动端的 rpx 单位是可以随着机型的大小进行自适应,因此我们以开发常用的尺寸(以 iphone 6 的 375 * 667 px)为例,在不超过这个值的限制上,去 给定父容器的宽高。
宽度设置为 100%,高度设置为如 1300 rpx(2rpx = 1px)
当获取到输入框焦点时,高度缩小,内容自动往上移动,并加入 动画 效果以让页面更加丝滑。
<!-- HTML -->
<!-- ispdFocus: 密码框是否拥有焦点;isuserFocus: 帐号输入框是否拥有焦点 -->
<view :style="(ispdFocus || isuserFocus) ? containerHeight.focus : containerHeight.blur"></view>
<!-- JavaScript -->
data() {
return {
containerHeight: {
focus: 'height:800rpx;transition:0.2s',
blur: 'height:1300rpx;transition:0.2s'
},
}
}
② 点击登录按钮后,需要有一个登录中 loading 反馈;登录成功后,使用 toast 弹窗提示后跳转。
登录的过程涉及到对接口的访问,此处用 settimeout 代替此过程进行模拟。
使用 uView-ui 中的按钮控件时,可以通过设置 loading 属性来让按钮呈现出加载状态,效果如图:
<u-button :loading="isLogining" @click="login">{{isLogining ? '' : '登 录'}}</u-button>
<u-toast ref="uToast"></u-toast>
login() {
// 密码正确
this.isLogining = true
setTimeout(()=>{
this.isLogining = false
this.$refs.uToast.show({
title: '登录成功',
type: 'success'
// 通过配置 url 可以指定在弹窗显示后跳转到哪个页面
// 如果是 tabBar 页面则还需要配置上 isTab: 'true'
// url: '',
// isTab: ''
})
},2000)
}
登录成功后,调用 uToast 来进行展示,效果如图:
密码错误的逻辑和弹窗这里就不再赘述,同理。
以下交互大家可以自行思考方案,demo 中提供的只是初步思路,如果有更好的思路欢迎私信或评论,我会将更好的实现方案后续更新到该模块下。
③ 聚焦输入框时应有合适的动画样式变化,让用户能够知道当前所处的输入框焦点在哪里。
④ 清除内容后需要重新将 焦点聚焦 到对应的 input 框上。
⑤ 登录按钮在禁用时,颜色变淡。
⑥ 登录页面 禁止下拉刷新 。
解决方案
// pages.json
{
"pages": [
{
// 页面注册
"path": "pages/index/index",
"style": {
// 禁止刷新
// ... : "false" => 写法错误,不能加双引号
"enablePullDownRefresh": false,
// 自定义导航栏(可理解为去除原生导航栏)
"navigationStyle": "custom"
}
}
],
...
}
重难点及解决方案
1. 输入框清空按钮焦点失去问题
清空按钮的存在逻辑是:当前输入框中 有内容 且 焦点存在 当前输入框中(notNull && isFocus)。该清空按钮存在焦点失去的问题,具体问题为:当点击清空按钮时,input 框失去焦点,因为我们的存在逻辑是必须有焦点才会出现,导致清空按钮消失,清空事件不会被触发。
为了解决这个问题,需要将失去焦点的事件用 setimeout 进行延迟控制,先清空后再执行失去焦点事件。该段内容与下方第2点代码进行合并讲解。
2. 清除内容后需要重新将 焦点聚焦 到对应的 input 框上。
1) u-input 基础输入框,根据文档,给定一个 focus 的属性,用于手动控制获取焦点;加上 @focus 和 @blur 方法用于监听输入框的焦点获取与失去。
再加上一张清空图片作为清空按钮,给定清空事件 clearInput,并且只在当输入框有内容且有焦点时才进行展示(ispdFocus 是通过 input 的 @focus 事件来触发使之变为 true)。
<!-- HTML -->
<view>
<u-input :focus="pd" v-model="userLoginInfo.password" type="password" :clearable="false" @focus="pdFocus" @blur="pdBlur"/>
<view class="clear" @click="clearInput('password')" v-show="userLoginInfo.password!=='' && ispdFocus">
<image :src="clearImg" class="img"></image>
</view>
</view>
2)data 中将 focus 初始值设为 false
// Script
data() {
return {
focus: false,
isFocus: false
}
}
3)在获取和失去焦点事件中,进行焦点是否获取的标志变化。值得一提的是,延时控制失去焦点( settimeout 设为 1),可以让清空按钮顺利执行完清空事件后,再执行 input 框焦点失去,否则会让清空事件失效。
pdFocus() {
this.ispdFocus = true
},
pdBlur() {
// 失去焦点事件先于清除事件触发,因此让其延迟即可先触发 clearInput 事件
setTimeout(() => {
this.ispdFocus = false
}, 1)
}
4)在清空内容的事件中编写逻辑
这里为何 pd 要先置为 false 再变为 true?focus 属性中是这样判定的,当你从 false 变为 true 的话,焦点才能 聚焦 到该 input 框上,而如果本来是从 true 变为 true 的话,那么是不发生变化的,因此无法达到将焦点聚焦在 input 框上的效果。
使用 nextTick 是为了保证让 pd = false 能够执行完毕后再进行操作,才能保证焦点的正确聚焦。
clearInput(value) {
switch (value) {
// ...
// 这里编写其他输入框的判断,如 user
case 'password':
this.userLoginInfo.password = ''
this.pd = false
this.$nextTick(() => {
this.pd = true
})
break
}
}
总结
① 在 blur 事件中通过延时来解决清空按钮失去焦点而导致失效的问题
② 在清空事件中使用 nextTick 控制 focus 来获取焦点
2. 在安卓端输入框之间切换时,焦点获取逻辑混乱,键盘弹起无规律
问题描述
在安卓端由于密码键盘的存在,导致在某些情况下与第三方键盘(如搜狗输入法)并不能很好地兼容。特别是在 type="text" 与 type="password" 之间切换时,更容易出现问题,而我发现的会导致此问题发生的,是如下的一行代码。
由于我希望在登录界面不展示出导航栏和状态栏,让其看起来更加清爽,搜索资料得知,去除状态栏(如电量等)的方法为:
onShow() {
// 去除状态栏
plus.navigator.setFullscreen(true);
},
但是加上这行代码后,会导致我登录界面在输入框之间切换焦点时,键盘会出现混乱弹起和收入的现象,焦点的获取也变得混乱,用户体验极差,但是目前没有在 iOS 端发现有此问题。
总结
① 在有 input 框的界面不建议加上如上代码,容易出现获取焦点混乱。
更多推荐
所有评论(0)