文章目录
- 一、目标完成页面
- 二、实战
- 2.1 定义数据
- 2.2 mock数据
- 2.3 封装顶部标题栏
- 2.4 封装评论Item
- 2.5 定义回复组件
- 2.6 主页面
- 三、小结
一、目标完成页面
二、实战
2.1 定义数据
export interface ReplyItem {
avatar: ResourceStr // 头像
author: string // 作者
id: number // 评论的id
content: string // 评论内容
time: string // 发表时间
area: string // 地区
likeNum: number // 点赞数量
likeFlag: boolean | null // 当前用户是否点过赞
}
export class ReplyItemModel implements ReplyItem {
id: number = 0
avatar: string | Resource = ''
author: string = ''
content: string = ''
time: string = ''
area: string = ''
likeNum: number = 0
likeFlag: boolean | null = null
constructor(model: ReplyItem) {
this.id = model.id
this.avatar = model.avatar
this.author = model.author
this.content = model.content
this.time = model.time
this.area = model.area
this.likeNum = model.likeNum
this.likeFlag = model.likeFlag
}
}
export enum CommentType {
MAIN,// 顶部
NORMAL// 普通
}
2.2 mock数据
export const mockReplyList: ReplyItemModel[] = [
new ReplyItemModel({
id: 1,
avatar: 'https://picx.zhimg.com/027729d02bdf060e24973c3726fea9da_l.jpg?source=06d4cd63',
author: '偏执狂-妄想家',
content: '更何况还分到一个摩洛哥[惊喜]',
time: '11-30',
area: '海南',
likeNum: 34,
likeFlag: false
}),
new ReplyItemModel({
id: 2,
avatar: 'https://pic1.zhimg.com/v2-5a3f5190369ae59c12bee33abfe0c5cc_xl.jpg?source=32738c0c',
author: 'William',
content: '当年希腊可是把1:0发挥到极致了',
time: '11-29',
area: '北京',
likeNum: 58,
likeFlag: false
}),
new ReplyItemModel({
id: 3,
avatar: 'https://picx.zhimg.com/v2-e6f4605c16e4378572a96dad7eaaf2b0_l.jpg?source=06d4cd63',
author: 'Andy Garcia',
content: '欧洲杯其实16队球队打正赛已经差不多,24队打正赛意味着正赛阶段在小组赛一样有弱队。',
time: '11-28',
area: '上海',
likeNum: 10,
likeFlag: false
}),
new ReplyItemModel({
id: 4,
avatar: 'https://picx.zhimg.com/v2-53e7cf84228e26f419d924c2bf8d5d70_l.jpg?source=06d4cd63',
author: '正宗好鱼头',
content: '确实眼红啊,亚洲就没这种球队,让中国队刷',
time: '11-27',
area: '香港',
likeNum: 139,
likeFlag: false
}),
new ReplyItemModel({
id: 5,
avatar: 'https://pic1.zhimg.com/v2-eeddfaae049df2a407ff37540894c8ce_l.jpg?source=06d4cd63',
author: '柱子哥',
content: '我是支持扩大的,亚洲杯欧洲杯扩到32队,世界杯扩到64队才是好的,世界上有超过200支队伍,欧洲区55支队伍,亚洲区47支队伍,即使如此也就六成出现率',
time: '11-27',
area: '旧金山',
likeNum: 29,
likeFlag: false
}),
new ReplyItemModel({
id: 6,
avatar: 'https://picx.zhimg.com/v2-fab3da929232ae911e92bf8137d11f3a_l.jpg?source=06d4cd63',
author: '飞轩逸',
content: '禁止欧洲杯扩军之前,应该先禁止世界杯扩军,或者至少把亚洲名额一半给欧洲。',
time: '11-26',
area: '里约',
likeNum: 100,
likeFlag: false
})
]
2.3 封装顶部标题栏
代码:
@Component
struct ZhiHuNavBar {
title: string = '标题'
build() {
Stack({ alignContent: Alignment.Start }) {
Row() {
Image($r('app.media.ic_left_arrow'))
.width(14)
.margin({ left: 3 })
}
.height(30)
.width(30)
.borderRadius(15)
.justifyContent(FlexAlign.Center)
.zIndex(999)
.backgroundColor(Color.Gray)
Text(this.title)
.width('100%')
.textAlign(TextAlign.Center)
}
.width('100%')
.height(50)
.padding({ left: 20, right: 20 })
.backgroundColor(Color.White)
.border({
color: '#e5e5e5',
width: {
bottom: 1
}
})
}
}
export { ZhiHuNavBar }
2.4 封装评论Item
代码:
import { ReplyItem, ReplyItemModel } from '../models'
@Preview
@Component
struct ZhiHuComponentItem {
@Prop item: ReplyItemModel = new ReplyItemModel({} as ReplyItem)
changeLike: () => void = () => {
}
build() {
Row({ space: 10 }) {
Image(this.item.avatar)
.width(28)
.borderRadius(14)
Column() {
Text(this.item.author)
.fontSize(16)
.fontWeight(FontWeight.Bold)
Text(this.item.content)
.fontSize(13)
.maxLines(3)
.lineHeight(18)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.margin({ top: 8 })
.padding({ bottom: 12 })
Row({ space: 5 }) {
Text(`${this.item.time} IP归属地${this.item.area}`)
.fontSize(12)
.fontColor('#999999')
Row({ space: 3 }) {
Image($r('app.media.ic_like'))
.width(12)
.fillColor(this.item.likeFlag ? Color.Red : Color.Black)
Text(this.item.likeNum.toString())
.fontSize(12)
.fontColor('#999999')
}
.onClick(() => {
this.changeLike()
})
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.alignItems(VerticalAlign.Top)
.padding(20)
}
}
export { ZhiHuComponentItem }
2.5 定义回复组件
代码:
@Component
struct ZhiHuReply {
@State content: string = ''
onSubmitContent: (content: string) => void = () => {
}
submitContent() {
if (this.content) {
this.onSubmitContent(this.content)
this.content = ''
}
}
build() {
Row({ space: 15 }) {
TextInput({ placeholder: '请输入', text: $$this.content })
.layoutWeight(1)
.height(40)
.onSubmit(() => {
this.submitContent()
})
Button('发布')
.onClick(() => {
this.submitContent()
})
}
.height(60)
.width('100%')
.padding({
left: 20,
right: 20
})
.border({
color: '#e5e5e5',
width: {
top: 1
}
})
}
}
export { ZhiHuReply }
2.6 主页面
import { ZhiHuComponentItem, ZhiHuNavBar, ZhiHuReply } from './components'
import { mockReplyList, ReplyItemModel, ReplyItem, CommentType } from './models'
@Entry
@Component
struct ZhiHuDemoPage {
@State commentList: ReplyItem[] = mockReplyList
@State mainComment: ReplyItemModel = new ReplyItemModel({
id: 999,
author: '周杰伦',
avatar: $r("app.media.zfb_pro_pic3"),
likeNum: 10,
likeFlag: false,
time: '03-02',
area: '北京',
content: '人到了一定的年龄新陈代谢就慢了,吃了胖不吃瘦了皱纹就多,要靠锻炼 '
})
private scroller: Scroller = new Scroller()
/**
* 点赞or取消点赞
* @param item
* @param type
*/
doChangeLike(item: ReplyItemModel, type?: CommentType) {
if (item.likeFlag) {
item.likeNum--
} else {
item.likeNum++
}
item.likeFlag = !item.likeFlag
if (type === CommentType.MAIN) {
this.mainComment = item
} else {
const index = this.commentList.findIndex(obj => obj.id === item.id)
// this.commentList[index] = new ReplyItemModel(item)
this.commentList.splice(index, 1, item)
}
}
/**
* 提交评论
* @param content
*/
onSubmitContent(content: string) {
const replyItem = new ReplyItemModel({
id: Math.random(),
author: '李佳琦',
avatar: $r("app.media.zfb_pro_pic3"),
likeNum: 0,
likeFlag: false,
time: `${(new Date().getMonth() + 1).toString().padStart(2, '0')}-${new Date().getDate()}`,
area: '上海',
content
})
this.commentList.unshift(replyItem)
this.scroller.scrollEdge(Edge.Top)
}
build() {
Column() {
// 标题栏
ZhiHuNavBar({ title: '评论' })
// 主评论
ZhiHuComponentItem({
item: this.mainComment,
changeLike: () => {
this.doChangeLike(this.mainComment, CommentType.MAIN)
}
})
// 分割线
Divider().strokeWidth(6)
// 评论数
Row() {
Text(`评论数${this.commentList.length}`)
}
.width('100%')
.height(50)
.padding({ left: 20 })
.border({
color: '#f3f4f5',
width: {
bottom: 1
}
})
// 普通评论列表
List({ scroller: this.scroller }) {
ForEach(this.commentList, (item: ReplyItemModel) => {
ListItem() {
ZhiHuComponentItem({
item,
changeLike: () => {
this.doChangeLike(item)
}
})
}
})
}
.layoutWeight(1)
// 回复模块
ZhiHuReply({
onSubmitContent: (content: string) => {
this.onSubmitContent(content)
}
})
}
.height('100%')
.width('100%')
.backgroundColor(Color.White)
}
}
三、小结
- 组件拆分及布局
- 父子组件数据传递
- 父子组件事件传递
- 数据更新及回调