注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下
如果大家觉得博主文章写的好的话,可以点下关注,博主会一直更新鸿蒙next相关知识
专栏地址: https://blog.csdn.net/qq_56760790/category_12794123.html
目录
[1. 基本介绍](#1. 基本介绍)
[2. 案例设计图](#2. 案例设计图)
[2.1 app应用](#2.1 app应用)
[2.2 登录页](#2.2 登录页)
[2.3 首页](#2.3 首页)
[2.4 添加/编辑页面](#2.4 添加/编辑页面)
[3. 项目结构](#3. 项目结构)
[4. 案例实现源码](#4. 案例实现源码)
[4.1 首先创建一个工程,然后将一些图片资源放在资源下面](#4.1 首先创建一个工程,然后将一些图片资源放在资源下面)
[2. 将AppScope下面的信息修改](#2. 将AppScope下面的信息修改)
[3. 修改module.json5文件](#3. 修改module.json5文件)
[4. 创建models目录,创建Student.ets文件](#4. 创建models目录,创建Student.ets文件)
[5. 创建conponents目录,,然后新增如下两个组件](#5. 创建conponents目录,,然后新增如下两个组件)
[6. 创建params目录,新增PageRouterParam.ets文件](#6. 创建params目录,新增PageRouterParam.ets文件)
[7. 创建utils目录,新增RdbUtil.ets文件](#7. 创建utils目录,新增RdbUtil.ets文件)
[8. 在pages目录下面新增三个页面](#8. 在pages目录下面新增三个页面)
[9. 修改EntryAbility.ets文件](#9. 修改EntryAbility.ets文件)
[4. 学习地址](#4. 学习地址)
1. 基本介绍
本案例涉及到多个鸿蒙相关技术知识点:
1、布局
2、配置文件
3、组件的封装和使用
4、路由的使用
5、应用数据持久化-关系型数据库的使用
鸿蒙学习交流
qq群号:767465523
2. 案例设计图
2.1 app应用
2.2 登录页
2.3 首页
2.4 添加/编辑页面
3. 项目结构
4. 案例实现源码
注意源码地址:
4.1 首先创建一个工程,然后将一些图片资源放在资源下面
icon.png
login.png
login_background.png
system.png
title.png
4.2 将AppScope下面的信息修改
4.3 修改module.json5文件
4.4 创建models目录,创建Student.ets文件
/**
* 学生信息
*/
export default interface Student {
/**
* 学生id
*/
id: number
/**
* 学生名称
*/
username: string
/**
* 年龄
*/
age: number
/**
* 爱好
*/
like: string
}
4.5 创建conponents目录,,然后新增如下两个组件
/**
* 学生列表组件
*/
import Student from '../models/Student'
import { promptAction, router } from '@kit.ArkUI'
import PageRouterParam from '../params/PageRouterParam'
import RdbUtil from '../utils/RdbUtil'
import { BusinessError } from '@kit.BasicServicesKit'
@Component
export default struct StudentListComponent {
@Link
studentList: Student[]
// 删除数据
remove(id: number) {
RdbUtil.deleteById(id)
.then((param) => {
console.log('remove student data success:' + param)
promptAction.showToast({
message: '删除数据成功'
})
router.replaceUrl({ url: 'pages/Index' })
}).catch((err: BusinessError) => {
console.log('remove student data fail:' + err)
promptAction.showToast({
message: '删除数据失败'
})
})
}
build() {
Column() {
// 数据标题
Row() {
Text('编号')
.TextStyle()
Text('姓名')
.TextStyle()
Text('年龄')
.TextStyle()
Text('爱好')
.TextStyle()
Text('操作')
.TextStyle()
.width('25%')
}
.width('100%')
.height(50)
.justifyContent(FlexAlign.SpaceAround)
.margin({ left: 20 })
// 学生数据
List({ space: 20 }) {
ForEach(this.studentList, (item: Student) => {
ListItem() {
Row() {
Text(item.id.toString())
.TextStyle()
Text(item.username)
.TextStyle()
Text(item.age.toString())
.TextStyle()
Text(item.like)
.TextStyle()
Text('编辑')
.TextStyle()
.fontColor(Color.Blue)
.onClick(() => {
router.pushUrl({
url: 'pages/Register',
params: new PageRouterParam('欢迎来到编辑学生界面', '确认修改', item.id)
})
})
Text('删除')
.TextStyle()
.fontColor(Color.Red)
.margin({ right: 10 })
.onClick(() => {
// 删除弹窗
AlertDialog.show(
{
title: '删除学生信息', // 标题
message: '是否需要删除所选学生信息?', // 内容
autoCancel: false, // 点击遮障层时,是否关闭弹窗。
alignment: DialogAlignment.Bottom, // 弹窗在竖直方向的对齐方式
offset: { dx: 0, dy: -20 }, // 弹窗相对alignment位置的偏移量
primaryButton: {
value: '取消',
action: () => {
console.info('Callback when the first button is clicked');
}
},
secondaryButton: {
value: '删除',
fontColor: '#D94838',
action: () => {
// 删除学生信息
this.remove(item.id)
}
},
cancel: () => { // 点击遮障层关闭dialog时的回调
console.info('Closed callbacks');
}
}
)
})
}
.width('100%')
.height(50)
.justifyContent(FlexAlign.SpaceAround)
.margin({ left: 20 })
.backgroundColor(Color.White)
.borderRadius(20)
}
}, (item: Student) => item.id.toString())
}
}.height('500')
}
}
@Extend(Text)
function TextStyle() {
.lineHeight(20)
.fontWeight(400)
.fontSize(15)
}
4.6 创建params目录,新增PageRouterParam.ets文件
/**
* 页面路由参数
*/
export default class PageRouterParam {
registerName: string = ''
buttonName: string = ''
studentId: number = 0
constructor(registerName: string, buttonName: string, studentId: number) {
this.registerName = registerName
this.buttonName = buttonName
this.studentId = studentId
}
}
4.7 创建utils目录,新增RdbUtil.ets文件
import relationalStore from '@ohos.data.relationalStore';
import Student from '../models/Student';
import { BusinessError } from '@ohos.base';
/**
* 关系型数据库工具类
*/
export default class RdbUtil {
/**
* 数据库对象
*/
private static rdbStore: relationalStore.RdbStore;
static setStore(store: relationalStore.RdbStore) {
RdbUtil.rdbStore = store;
}
static getStore(): relationalStore.RdbStore {
return RdbUtil.rdbStore;
}
/**
* 执行sql
* @param sql
* @returns
*/
static executeSql(sql: string): Promise<void> {
return RdbUtil.getStore().executeSql(sql);
}
/**
* 插入数据
* @param tableName
* @param data
* @returns
*/
static insert(tableName: string, data: relationalStore.ValuesBucket): Promise<number> {
return RdbUtil.getStore().insert(tableName, data);
}
/**
* 查询数据
* @returns
*/
static queryAll(): Promise<Array<Student>> {
let predicates = new relationalStore.RdbPredicates('STUDENT');
return new Promise<Array<Student>>((resolve, reject) => {
RdbUtil.getStore().query(predicates).then((result) => {
let students = new Array<Student>();
while (result.goToNextRow()) {
students.push({
id: result.getLong(0),
username: result.getString(1),
age: result.getLong(2),
like: result.getString(3)
});
}
resolve(students);
}).catch((error: BusinessError) => {
reject(error)
})
})
}
/**
* 删除
* @param id
* @returns
*/
static deleteById(id: number) {
let predicates = new relationalStore.RdbPredicates('STUDENT');
predicates.equalTo('ID', id)
return RdbUtil.getStore().delete(predicates);
}
/**
* 更新
* @param id
* @param data
* @returns
*/
static updateById(id: number, data: relationalStore.ValuesBucket) {
let predicates = new relationalStore.RdbPredicates('STUDENT');
predicates.equalTo('ID', id)
return RdbUtil.getStore().update(data, predicates);
}
}
4.8 在pages目录下面新增三个页面
import StudentListComponent from '../components/StudentListComponent'
import Student from '../models/Student'
import { promptAction, router } from '@kit.ArkUI'
import PageRouterParam from '../params/PageRouterParam'
import TitleComponent from '../components/TitileComponent'
import RdbUtil from '../utils/RdbUtil'
import { BusinessError } from '@kit.BasicServicesKit'
@Entry
@Component
struct Index {
// 学生数组数据
@State studentList: Student[] = []
/**
* 查询数据
*/
onPageShow() {
// 从关系型数据库中获取
this.studentList = []
RdbUtil.queryAll()
.then((students: Array<Student>) => {
this.studentList = students
promptAction.showToast({ message: '获取学生信息成功' })
}).catch((error: BusinessError) => {
promptAction.showToast({
message: ' 获取学生信息失败 '
})
})
}
build() {
Column() {
// 标题组件
TitleComponent()
Row() {
// 学生数据
Text('学生数据')
.TextIndexStyle()
// 添加
Text('添加')
.fontColor(Color.Blue)
.TextIndexStyle()
.onClick(() => {
router.pushUrl({ url: 'pages/Register', params: new PageRouterParam('欢迎来到添加学生界面', '注册', 0) })
})
}.width('80%')
.height(40)
.justifyContent(FlexAlign.SpaceBetween)
// 学生成绩展示
StudentListComponent({ studentList: this.studentList })
}
.height('100%')
.width('100%')
.backgroundImage($r('app.media.login_background'))
.backgroundImageSize({ width: '100%', height: '100%' })
}
}
@Extend(Text)
function TextIndexStyle() {
.lineHeight(20)
.fontWeight(400)
.fontSize(15)
}
import { promptAction, router } from '@kit.ArkUI';
@Entry
@Component
struct Login {
@State account: string = 'admin';
@State password: string = '123456';
/**
* 登录
*/
login() {
// 校验账号密码是否符合要求
if (this.account === 'admin' || this.password === '123456') {
promptAction.showToast({ message: '登录成功' })
router.pushUrl({
url: 'pages/Index'
})
} else {
promptAction.showToast({ message: '登录失败' })
router.pushUrl({
url: 'pages/login'
})
}
}
build() {
Column() {
Column() {
// 登录图片
Image($r('app.media.login'))
.width(100)
.height(100)
.margin({ top: 200 })
// 学生管理系统
Text('学生管理系统')
.padding(20)
.fontSize(20)
.fontWeight(600)
// 输入账号密码
TextInput({ text: this.account, placeholder: '请输入账号' })
.TextInputLoginStyle()
.onChange((value) => {
this.account = value
})
// 请输入密码
TextInput({ text: this.password, placeholder: '请输入密码' })
.TextInputLoginStyle()
.type(InputType.Password)
.onChange((value) => {
this.password = value
})
// 登录
Button('登录', { stateEffect: true })
.fontColor(Color.White)
.width(300)
.height(40)
.type(ButtonType.Normal)
.onClick(() => {
this.login()
})
}
}
.height('100%')
.width('100%')
.backgroundImage($r('app.media.login_background'))
.backgroundImageSize({ width: '100%', height: '100%' })
}
}
@Extend(TextInput)
function TextInputLoginStyle() {
.placeholderFont({ size: 15 })
.width(300)
.height(40)
.margin({ bottom: 10 })
.borderRadius(0)
}
import { promptAction, router } from '@kit.ArkUI'
import TitleComponent from '../components/TitileComponent'
import PageRouterParam from '../params/PageRouterParam'
import { relationalStore } from '@kit.ArkData'
import RdbUtil from '../utils/RdbUtil'
import { BusinessError } from '@kit.BasicServicesKit'
@Entry
@Component
struct Register {
@State username: string = ''
@State age: number = 0
@State like: string = ''
@State registerName: string = '欢迎来到添加学生界面'
@State buttonName: string = '注册'
@State studentId: number = 0
aboutToAppear() {
// 获取路由参数
const param = router.getParams() as PageRouterParam
this.registerName = param.registerName
this.buttonName = param.buttonName
this.studentId = param.studentId
}
register() {
// 校验参数
if (!this.username || !this.age || !this.like) {
promptAction.showToast({
message: this.buttonName + '失败,请填写学生信息'
})
return
}
if (this.studentId === 0) {
// 注册
const valueBucket: relationalStore.ValuesBucket = {
'USERNAME': this.username,
'AGE': this.age,
'LIKE': this.like
};
RdbUtil.insert('STUDENT', valueBucket)
.then((data) => {
console.log('insert data success:' + JSON.stringify(data))
promptAction.showToast({
message: '注册成功'
})
}).catch((error: BusinessError) => {
console.log('insert data fail:' + error)
promptAction.showToast({
message: '注册失败 '
})
})
} else {
// 修改
const valueBucket: relationalStore.ValuesBucket = {
'USERNAME': this.username,
'AGE': this.age,
'LIKE': this.like
};
RdbUtil.updateById(this.studentId, valueBucket)
.then((data) => {
console.log('update student success:' + JSON.stringify(data))
promptAction.showToast({
message: '修改成功'
})
}).catch((err: BusinessError) => {
console.log('update student fail:' + err)
promptAction.showToast({
message: ' 修改失败 '
})
})
}
// 跳转到首页
router.replaceUrl({ url: 'pages/Index' })
}
build() {
Column() {
// 欢迎页面
TitleComponent({ name: this.registerName })
// 注册功能
TextInput({ placeholder: '请输入学生名称' })
.TextInputRegisterStyle()
.onChange((value) => {
this.username = value
})
TextInput({ placeholder: '请输入学生年龄' })
.TextInputRegisterStyle()
.onChange((value) => {
this.age = Number(value)
})
TextInput({ placeholder: '请输入学生爱好' })
.TextInputRegisterStyle()
.onChange((value) => {
this.like = value
})
Button(this.buttonName)
.width(300)
.type(ButtonType.Normal)
.stateEffect(true)
.onClick(() => {
// 注册或者修改
this.register()
})
}
.height('100%')
.width('100%')
.backgroundImage($r('app.media.login_background'))
.backgroundImageSize({ width: '100%', height: '100%' })
}
}
@Extend(TextInput)
function TextInputRegisterStyle() {
.placeholderFont({ size: 15 })
.width(300)
.height(40)
.margin({ bottom: 10 })
.borderRadius(0)
}
4.9 修改EntryAbility.ets文件
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { promptAction, window } from '@kit.ArkUI';
import { relationalStore } from '@kit.ArkData';
import RdbUtil from '../utils/RdbUtil';
import { BusinessError } from '@kit.BasicServicesKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
}
onDestroy(): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
// 创建数据库
const STORE_CONFIG: relationalStore.StoreConfig = {
name: 'study_manage.db', // 数据库文件名
securityLevel: relationalStore.SecurityLevel.S3, // 数据库安全级别
encrypt: false, // 可选参数,指定数据库是否加密,默认不加密
customDir: 'customDir/subCustomDir', // 可选参数,数据库自定义路径。数据库将在如下的目录结构中被创建:context.databaseDir + '/rdb/' + customDir,其中context.databaseDir是应用沙箱对应的路径,'/rdb/'表示创建的是关系型数据库,customDir表示自定义的路径。当此参数不填时,默认在本应用沙箱目录下创建RdbStore实例。
isReadOnly: false // 可选参数,指定数据库是否以只读方式打开。该参数默认为false,表示数据库可读可写。该参数为true时,只允许从数据库读取数据,不允许对数据库进行写操作,否则会返回错误码801。
};
relationalStore.getRdbStore(this.context, STORE_CONFIG, (err, store) => {
if (err) {
console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`);
return;
}
console.info(`Succeeded in getting RdbStore.`);
//保存store, 方便后面我们对数据库的操作
RdbUtil.setStore(store)
// 创建学生表
const SQL_CREATE_TABLE =
'CREATE TABLE IF NOT EXISTS STUDENT (ID INTEGER PRIMARY KEY AUTOINCREMENT, USERNAME TEXT NOT NULL, AGE INTEGER,LIKE TEXT NOT NULL)'; // 建表Sql语句
RdbUtil.executeSql(SQL_CREATE_TABLE)
.then(() => {
console.log('success create table')
}).catch((err: BusinessError) => {
console.log('fail create table')
})
})
windowStage.loadContent('pages/Login', (err) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
});
}
onWindowStageDestroy(): void {
// Main window is destroyed, release UI related resources
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
}
onForeground(): void {
// Ability has brought to foreground
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
}
onBackground(): void {
// Ability has back to background
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
}
}