一、引言
- 描述:如何在鸿蒙系统中开发一个功能齐全的登录模块,具备准确的定位提示。
- 难度:初级
- 知识点:
- 1、Router页面路由
- 2、CustomDialog自定义弹窗
- 3、Popup气泡提示
- 4、setTimeout定时器
- 效果:
二、设计
1、UI设计
(1)主布局
关于布局构建,可以参考同栏目中的文章,以下是大致的布局,后面再完善
@Entry
@Component
struct Index {
@State name: string = ""
@State pass: string = ""
@State btnLogin: string = "登录"
build() {
Row() {
Column() {
// person
Image($r('app.media.person')).width(100).height(100).margin({top:80, bottom:50})
// data
TextArea({ placeholder : "账号/电话号码"})
.margin(15)
.onChange((value: string) => {
// TOD 数据绑定
this.name = value
})
TextInput({ placeholder : "密码", text : this.pass})
.margin(15)
.type(InputType.Password)
.onChange((value: string) => {
// TOD 数据绑定
this.pass = value
})
// btn
Button(this.btnLogin, { type: ButtonType.Normal, stateEffect: true })
.borderRadius(18)
.backgroundColor(0x317aff)
.width(90)
.height(40)
.margin({top:50})
.onClick(() => {
// TODO 登录逻辑
...
})
}
}
}
}
(2)CustomDialog
CustomDialog(弹窗):可用于广告、中奖、警告、软件更新等与用户交互响应操作。
- 第一步:@CustomDialog装饰器用于装饰自定义弹框,此装饰器内进行自定义内容。
// 弹出登录成功的信息
@CustomDialog
struct CustomDialogExample {
controller: CustomDialogController
build() {
Column() {
Text('登录成功')
.fontSize(20)
.margin({ top: 10, bottom: 10 })
.borderRadius(5)
}
}
}
- 第二步:@CustomDialog装饰器用于装饰自定义弹框,此装饰器内进行自定义内容。
@Entry
@Component
struct Index {
// 创建构造器
dialogController: CustomDialogController = new CustomDialogController({
builder: CustomDialogExample({}),
})
...
}
- 第三步:点击与onClick事件绑定的组件使弹窗弹出。
@Entry
@Component
struct Index {
...
build() {
Row() {
Column() {
Flex({justifyContent:FlexAlign.Center}) {
Button(this.btnLogin, { type: ButtonType.Normal, stateEffect: true })
.borderRadius(18)
.backgroundColor(0x317aff)
.width(90)
.height(40)
.margin({ top: 50 })
.onClick(() => {
// 打开自定义弹窗
this.dialogController.open()
// 定时关闭弹窗(1s)
setTimeout(() => {
// 关闭自定义弹窗
this.dialogController.close()
}, 1000)
})
}
}
}
}
}
(3)Popup
Popup(气泡提示):可绑定在组件上显示气泡弹窗提示,设置弹窗内容、交互逻辑和显示状态。
- 以当个输入框为例
@Entry
@Component
struct Index {
@State name: string = ""
@State pass: string = ""
@State btnLogin: string = "登录"
@State handlePopup_name: boolean = false
@State handlePopup_pass: boolean = false
@State handlePopup_btn: boolean = false
// TODO 创建构造器
build() {
Row() {
Column() {
// person
...
// data
...
TextInput({ placeholder : "密码", text : this.pass})
.margin(15)
.type(InputType.Password)
.onChange((value: string) => {
...
})
.bindPopup(this.handlePopup_pass, {
message: '密码为空',
})
// btn
Flex({justifyContent:FlexAlign.Center}) {
Button(this.btnLogin, { type: ButtonType.Normal, stateEffect: true })
.borderRadius(18)
.backgroundColor(0x317aff)
.width(90)
.height(40)
.margin({ top: 50 })
.onClick(() => {
...
// 密码为空,气泡提示
if (this.pass == "") {
this.handlePopup_pass = !this.handlePopup_pass
}
...
})
...
}
}
}
}
}
2、逻辑设计
关于此处的Router和setTimeout,主攻前端的小伙伴肯定不陌生,科班学习的小伙伴多少也有印象,这里我就简单讲一下。
(1)Router
Router(路由):在应用程序中实现不同页面之间的跳转和数据传递
-
第一步:声明URL
-
第二步:跳转并传递数值
import router from '@ohos.router';
// 弹出登录成功的信息
...
@Entry
@Component
struct Index {
...
// 创建构造器
...
build() {
Row() {
Column() {
...
// btn
Flex({justifyContent:FlexAlign.Center}) {
Button(this.btnLogin, { type: ButtonType.Normal, stateEffect: true })
.borderRadius(18)
.backgroundColor(0x317aff)
.width(90)
.height(40)
.margin({ top: 50 })
.onClick(() => {
...
router.push({
url: 'pages/UserInfo',
// 传递数值
params: {
name: this.name,
pass: this.pass
}
})
})
}
}
}
}
}
- 第三步:被选定界面,接收数值
import router from '@ohos.router';
@Entry
@Component
struct UserInfo {
// 接收数据
@State name: string = router.getParams()?.['name'];
@State pass: string = router.getParams()?.['pass'];
build() {
Row() {
Column(){
Text("账号:" + this.name).fontSize(50)
Text("密码:" + this.pass).fontSize(50)
Button('返回')
.onClick(() => {
router.back()
})
}
}
}
}
(2)setTimeout
setTimeout(定时器):指定多久后(ms)完成方法(function)
setTimeout(() => {
// 关闭自定义弹窗
this.dialogController.close()
// 路由跳转
router.push({
url: 'pages/UserInfo',
params: {
name: this.name,
pass: this.pass
}
})
}, 1000)
三、附件
1、完整代码
- Index.ets
import router from '@ohos.router';
// 弹出登录成功的信息
@CustomDialog
struct CustomDialogExample {
controller: CustomDialogController
build() {
Column() {
Text('登录成功')
.fontSize(20)
.margin({ top: 10, bottom: 10 })
.borderRadius(5)
}
}
}
@Entry
@Component
struct Index {
@State name: string = ""
@State pass: string = ""
@State btnLogin: string = "登录"
@State handlePopup_name: boolean = false
@State handlePopup_pass: boolean = false
@State handlePopup_btn: boolean = false
// 创建构造器
dialogController: CustomDialogController = new CustomDialogController({
builder: CustomDialogExample({}),
})
build() {
Row() {
Column() {
// person
Image($r('app.media.person')).width(100).height(100).margin({top:80, bottom:50})
// data
TextArea({ placeholder : "账号/电话号码"})
.margin(15)
.onChange((value: string) => {
this.name = value
this.handlePopup_name = false
this.handlePopup_btn = false
})
.bindPopup(this.handlePopup_name, {
message: '账号为空',
})
TextInput({ placeholder : "密码", text : this.pass})
.margin(15)
.type(InputType.Password)
.onChange((value: string) => {
this.pass = value
this.handlePopup_pass = false
this.handlePopup_btn = false
})
.bindPopup(this.handlePopup_pass, {
message: '密码为空',
})
// btn
Flex({justifyContent:FlexAlign.Center}) {
Button(this.btnLogin, { type: ButtonType.Normal, stateEffect: true })
.borderRadius(18)
.backgroundColor(0x317aff)
.width(90)
.height(40)
.margin({ top: 50 })
.onClick(() => {
if (this.name == "") {
this.handlePopup_name = !this.handlePopup_name
} else if (this.pass == "") {
this.handlePopup_pass = !this.handlePopup_pass
} else if (this.name == "123456" && this.pass == "666") {
console.log("登录成功!")
this.dialogController.open()
// 定时任务,跳转到第二个界面,两秒后
setTimeout(() => {
// 关闭自定义弹窗
this.dialogController.close()
// 路由跳转
router.push({
url: 'pages/UserInfo',
params: {
name: this.name,
pass: this.pass
}
})
}, 1000)
} else {
this.handlePopup_btn = !this.handlePopup_btn
}
})
.bindPopup(this.handlePopup_btn, {
message: '账号或密码错误',
})
}
}
}
}
}
- UserInfo.ets
import router from '@ohos.router';
@Entry
@Component
struct UserInfo {
@State name: string = router.getParams()?.['name'];
@State pass: string = router.getParams()?.['pass'];
build() {
Row() {
Column(){
Text("账号:" + this.name).fontSize(50)
Text("密码:" + this.pass).fontSize(50)
Button('返回')
.onClick(() => {
router.back()
})
}
}
}
}