企业网站建设公司司,今天刚刚长沙又增加了一例,揭阳市网站建设,自己怎么建h5商城网站效果展示 功能描述
整个页面分为三大模块#xff1a;顶部 主体【评论列表】 底部。
点击顶部的最新和最热按钮可以进行切换#xff0c;点击最新按钮的时候主体部分的评论列表是按照时间由近至远进行排列展示#xff0c;点击最热按钮的时候主体部分的评论列表是按照点赞数…效果展示 功能描述
整个页面分为三大模块顶部 主体【评论列表】 底部。
点击顶部的最新和最热按钮可以进行切换点击最新按钮的时候主体部分的评论列表是按照时间由近至远进行排列展示点击最热按钮的时候主体部分的评论列表是按照点赞数量从多到少进行排列展示的。
主体部分中可以对每一条评论进行点赞当点赞的时候该条评论的点赞图标及其颜色发生变化该条评论的数量和颜色会发生变化。
底部区域中可以在输入框中进行评论的书写书写完评论之后按下回车键可以将书写的内容添加到上方主体部分的评论列表当中同时将输入框中的内容进行清空处理但如果输入的内容为空的时候按回车键会弹出一个提示警告用户输入的内容不能为空。
涉及知识 蓝色字体如果是点击后不能进行链接跳转的就说明在文章的下方对其有解释说明。 1、List 列表组件
列表包含一系列相同宽度的列表项。适合连续、多行呈现同类数据例如图片和文本。
仅支持ListItem、ListItemGroup子组件支持渲染控制类型if/else、ForEach、LazyForEach和Repeat。
List(value?:{space?: number | string, initialIndex?: number, scroller?: Scroller})
参数说明
参数名类型必填说明spacenumber string否子组件主轴方向的间隔。 默认值0 参数类型为number时单位为vp 说明设置为负数或者大于等于List内容区长度时按默认值显示。space参数值小于List分割宽度时子组件主轴方向的间隔取分割线宽度。initialIndexnumber否设置当前List初次加载时视口起始位置显示的item的索引值。 默认值0 说明设置为负数或超过了当前List最后一个item的索引值时视为无效取值无效取值按默认值显示。scrollerScroller否可滚动组件的控制器。用于与可滚动组件进行绑定。 说明不允许和其他滚动类组件绑定同一个滚动控制对象。 属性
除支持通用属性和滚动组件通用属性外还支持以下属性
属性说明listDirection(value: Axis)设置List组件排列方向 默认值Axis.Verticaldivider(value: {strokeWidth: Length; color?: ResourceColor; startMargin?: Length; endMargin?: Length;} | null,) ListItem分割线样式。 - strokeWidth: 分割线的线宽。 - color: 分割线的颜色。 默认值0x08000000 - startMargin: 分割线与列表侧边起始端的距离。 默认值0单位vp - endMargin: 分割线与列表侧边结束端的距离。 默认值0单位vp scrollBar(value: BarState) 滚动条状态。 默认值BarState.Auto 说明 API version 9及以下版本默认值为BarState.OffAPI version 10及以上版本的默认值为BarState.Auto。 cachedCount(value: number) ListItem/ListItemGroup的预加载数量。 默认值1 editMode(value: boolean) 当前List组件是否处于可编辑模式。 默认值false edgeEffect(value: EdgeEffect, options?: EdgeEffectOptions)设置边缘滑动效果。chainAnimation(value: boolean) 是否启用链式联动动效。 默认值false不启用链式联动。true启用链式联动。 lanes(value: number | LengthConstrain, gutter?: Dimension)设置List组件的布局列数或行数。gutter为列间距当列数大于1时生效。alignListItem(value: ListItemAlign) 交叉轴方向的布局方式。 默认值ListItemAlign.Start 更多属性可参考官网…………
Axis参数取值说明
取值描述Vertical方向为纵向Horizontal方向为横向
Length参数取值说明
取值说明string需要显示指定像素单位如100px也可以设置百分比字符串比如100% 说明不指定像素单位时默认单位vpnumber默认单位vpResource资源引用类型引入系统资源或者引用资源中的尺寸
ResourceColor参数取值说明
取值说明Color颜色枚举值numberHEX格式颜色支持rgb或者argb。示例0xffffff0xffff0000。number无法识别传入位数格式选择依据值的大小例如0x00ffffff作rgb格式解析stringrgb或者argb格式颜色。示例#ffffff, #ff000000, rgb(255, 100, 255), rgba(255, 100, 255, 0.5)。Resource使用引入资源的方式引入系统资源或者应用资源中的颜色。
BarState参数取值说明
取值说明Off不显示On常驻显示Auto按需显示触摸时显示2s后消失 EdgeEffect参数取值说明
取值说明Spring弹性物理动效滑动到边缘后可以根据初始速度或通过触摸事件继续滑动一段距离松手后回弹。Fade阴影效果滑动到边缘后会有圆弧状的阴影。None滑动到边缘后无效果。 2、IconFont 字体图标的使用
①iconfont官网选图标 → 加入项目 → 下载
②注册成自定义字体
③设置字体使用
优势任意放大缩小不失真可以修改颜色。
3、Prop - 父子单向
Prop 装饰的变量可以和父组件建立单向的同步关系
Prop 装饰的变量是可变的但是变化不会同步回父组件 代码演示
index.ets
import Header from ../components/Header
import { infoItem } from ../components/infoItem
import Footer from ../components/Footer
import font from ohos.font;
import { CommentData, createListRange } from ../model/CommentData;Entry
Component
struct Index {// 一加载index入口页面就进行注册// aboutToAppear 会在组件一加载时自动调用执行生命周期函数aboutToAppear(): void {// 注册字体font.registerFont({familyName: myFont,familySrc: /fonts/iconfont.ttf})// 已进入页面的时候先默认按照时间进行排序this.handleSort(1)}State remarkList: CommentData[] createListRange()//点赞handleLike(index: number) {// 子调用父的方法时每个子组件都可以调用父组件的方法需要加以区分【使用数组下标】// 对于复杂类型状态对象、状态数组只会对第一层数据进行监视变化let itemData this.remarkList[index]if (itemData.isLike) {itemData.likeNum - 1} else {itemData.likeNum 1}itemData.isLike !itemData.isLike// 解决方法使用 数组.splice(从哪开始删除删除几个替换的项1替换的项2...)this.remarkList.splice(index, 1, itemData)}// 处理评论回车提交handleSubmit(content: string) {// 往评论数组的最前边插入一条数据if (content.trim().length) {const newItem: CommentData new CommentData(https://profile-avatar.csdnimg.cn/d29edf7348024b8f834e7a8b90887173_qq_45569925.jpg!1, 我,new Date().getTime(), 0, 0, content, false)this.remarkList.unshift(newItem)} else {AlertDialog.show({message: 输入的评论不能为空})}}// 处理点击最新/最热进行排序handleSort(type: number) {// 按照最新进行排序if (type 1) {this.remarkList this.remarkList.sort((a, b) {return b.time - a.time //按照时间进行由近到远进行排序})} else if (type 2) {// 按照最热进行排序this.remarkList this.remarkList.sort((a, b) {// a前一项b后一项如果后一项➖前一项 0则交换位置否则不变return b.likeNum - a.likeNum //按照点赞数降序排列})}}build() {Column() {// 头部组件Header({onSort: (type: number) {this.handleSort(type)}})// 主体内容组件List() {ForEach(this.remarkList, (item: CommentData, index: number) {ListItem() {// 将item对象通过prop传值传递下去infoItem({index: index,itemObj: item,/**父组件的方法如果抽取出来直接传递给子组件* 会有this指向问题this通常直接指向调用者* 需要用箭头函数包一层保证this还是指向父组件* */onLikeClick: (index: number) {// 此处的this指向的就是父组件this.handleLike(index)}})}.padding(10)})}.padding({ bottom: 10 }).layoutWeight(1).width(100%)// 底部评论组件Footer({onSubmitComment: (content: string) {this.handleSubmit(content)}})}.width(100%).height(100%)}
}
Header.ets
// 头部组件Extend(Button)
// isAct当前项是否处于高亮状态
function btnStyle(isAct: boolean) {.width(46).height(32).fontSize(12).padding({ left: 5, right: 5 }).backgroundColor(isAct ? #fff : #F7F8FA).fontColor(#2F2E33).border({width: isAct ? 1 : 0,color: #e4e5e6})
}Component
struct Header {State current: number 1State isAct: boolean trueonSort (type: number) {}build() {Row() {Text(全部评论).fontSize(20).fontWeight(700)Row() {// 如果不设置{ stateEffect: false }点击按钮的时候会有默认激活样式Button(最新, { stateEffect: false }).btnStyle(this.isAct).onClick(() {this.isAct truethis.onSort(1)})Button(最热, { stateEffect: false }).btnStyle(!this.isAct).onClick(() {this.isAct falsethis.onSort(2)})}.borderRadius(20).backgroundColor(#F7F8FA)}.padding(16).width(100%).justifyContent(FlexAlign.SpaceBetween)}
}export default Header
infoItem.ets
import { CommentData } from ../model/CommentDataComponent
export struct infoItem {Prop index: numberProp itemObj: CommentDataonLikeClick (index: number) {}build() {Row() {Image(this.itemObj.avatar).width(30).aspectRatio(1)//保证宽高比是1:1.borderRadius(50)Column({ space: 8 }) {Row() {Text(this.itemObj.name).margin({ left: 8, right: 12 }).fontSize(13).fontColor(Color.Gray)Image(this.itemObj.levelIcon).width(20).aspectRatio(1) //保证宽高比是1:1}Text(this.itemObj.commentTxt).margin({ left: 8 }).fontSize(13).fontColor(Color.Black)Row() {Text(this.itemObj.timeString).fontSize(10).fontColor(Color.Gray)Row({ space: 2 }) {Text(this.itemObj.isLike ? \uec8c : \ue600).fontFamily(myFont).fontSize(15).fontColor(this.itemObj.isLike ? Color.Blue : )Text(this.itemObj.likeNum.toString()).fontSize(12).fontColor(this.itemObj.isLike ? Color.Blue : )}.alignItems(VerticalAlign.Center).onClick(() {// 需要调用父组件的方法才能够真正的修改父组件的数据this.onLikeClick(this.index)})}.width(100%).margin({ left: 8 }).padding({ right: 10 }).justifyContent(FlexAlign.SpaceBetween).alignItems(VerticalAlign.Center).align(Alignment.End)}.layoutWeight(1).alignItems(HorizontalAlign.Start)}.width(100%).alignItems(VerticalAlign.Top).justifyContent(FlexAlign.SpaceBetween)}
}
Footer.ets
// 底部区域组件
Component
struct Footer {State msg: string onSubmitComment (msg: string) {}build() {Row({ space: 10 }) {Row() {Text(\ue7a0).fontFamily(myFont).fontColor(Color.Gray)TextInput({placeholder: 写评论...,// text: this.msg, // 单向数据绑定即输入框中的值改变的时候不会印象msg的值text: $$this.msg // 双向数据绑定}).height(100%).backgroundColor(Color.Transparent)// 监听输入框的回车事件.onSubmit(() {// 这里不能直接添加需要调用父组件传递过来的方法this.onSubmitComment(this.msg)// 按下回车键将数据添加成功之后将输入框清空this.msg })}.padding({ left: 20, right: 20 }).layoutWeight(1).height(40).borderRadius(20).backgroundColor(#f6f6f6)Text(\ue600).fontFamily(myFont).fontSize(20)Text(\ue607).fontFamily(myFont).fontSize(18)}.padding(10).width(100%).height(50).backgroundColor(Color.White)}
}export default Footer
CommentData.ets
// 准备评论的数据类
export class CommentData {avatar: string; // 头像name: string; //昵称level: number; //用户等级likeNum: number; //点赞数量commentTxt: string; //评论内容isLike: boolean; //是否点赞levelIcon: Resource; //level等级timeString: string; //发布时间--基于时间戳处理后展示给用户看的time: number; //时间戳constructor(avatar: string, name: string, time: number, level: number, likeNum: number, commentTxt: string,isLike: boolean) {this.avatar avatarthis.name namethis.level levelthis.likeNum likeNumthis.commentTxt commentTxtthis.isLike isLikethis.levelIcon this.convertLevel(this.level)this.timeString this.convertTime(time)this.time time}// 基于传入的level转换为图片路径convertLevel(level: number): Resource {return $r(app.media.level_${level})}convertTime(lastTimeSatmp: number): string {const nowTimestamp new Date().getTime() //当前时间戳const timeDifference (nowTimestamp - lastTimeSatmp) / 1000 //转换为秒【当前时间与传入时间之间的时间差】if (timeDifference 0 || timeDifference 0) {return 刚刚} else if (timeDifference 60) {return ${Math.floor(timeDifference)}秒前} else if (timeDifference 3600) {return ${Math.floor(timeDifference / 60)}分钟前} else if (timeDifference 86400) {return ${Math.floor(timeDifference / 3600)}小时前} else if (timeDifference 604800) {return ${Math.floor(timeDifference / 86400)}天前} else if (timeDifference 31536000) {return ${Math.floor(timeDifference / 2592000)}个月前} else {return ${Math.floor(timeDifference / 31536000)}年前}}
}// 封装一个方法, 创建假数据
export const createListRange (): CommentData[] {let result: CommentData[] new Array()result [new CommentData(https://fastly.picsum.photos/id/770/600/600.jpg?hmactuK9EHg1ifTU3xKAiZj2nHSdWy4mk7enhylgOc2BW7E,雪山飞狐, 1725503122785, Math.floor(Math.random() * 6), Math.floor(Math.random() * 100),23年一年干完的事真的非常仓促, false),new CommentData(https://fastly.picsum.photos/id/225/600/600.jpg?hmacv97zt_t4mxeyMttX_m09pxhCvftiTxFR1MMBZi5HQxs,千纸鹤, 1725504541300, Math.floor(Math.random() * 6), Math.floor(Math.random() * 100),Netty对象池源码分析来啦juejin.cn欢迎点赞[奸笑], false),new CommentData(https://fastly.picsum.photos/id/122/600/600.jpg?hmac1oA93YbjYVt96DcJcGQ5PLthzjUsdtrnBQaM0USBozI,烟雨江南, 1725408000000, Math.floor(Math.random() * 6), Math.floor(Math.random() * 100),有一个不听劝的Stable Diffusion出图的小伙伴找我给她装填脑。 一个资深的IT工程师不能受这个委屈。, false),new CommentData(https://fastly.picsum.photos/id/654/600/600.jpg?hmacewnK6Bx_MKQLJa9waZOV1xNO7--K5oSwCShtz1JDYw8,魔法小精灵, 1697484201123, Math.floor(Math.random() * 6), Math.floor(Math.random() * 100),有一点可以确信 前后端开发界限越来越模糊。后端可以不写 但是不能不会。, false),new CommentData(https://fastly.picsum.photos/id/345/600/600.jpg?hmacEQflzbIadAglm0RzotyKXM2itPfC49fR3QE7eW_UaPo,独行侠, 1704067200000, Math.floor(Math.random() * 6), Math.floor(Math.random() * 100),今天看到一个帖子挺有意思的。, false),new CommentData(https://fastly.picsum.photos/id/905/600/600.jpg?hmacDvIKicBZ45DEZoZFwdZ62VbmaCwkK4Sv7rwYzUvwweU,枫叶飘零, 1706745600000, Math.floor(Math.random() * 6), Math.floor(Math.random() * 100),我想了搞钱的路子 1投资理财 后来发下不投资就是最好的理财 2买彩票后来发现彩票都是人家预定好的根本不是随机的卒 3开店创业隔行如隔山开店失败卒。,false),new CommentData(https://fastly.picsum.photos/id/255/600/600.jpg?hmac-lfdnAl71_eAIy1OPAupFFPh7EOJPmQRJFg-y7lRB3s,星空漫步, 1707523200000, Math.floor(Math.random() * 6), Math.floor(Math.random() * 100),优胜劣汰自然选择吧没什么好怪的。都是crud招个大学生就能干了。, false),new CommentData(https://fastly.picsum.photos/id/22/600/600.jpg?hmacQEZq7KUHwBZCt3kGSEHMwJlZfnzCxCeBgHjYj7iQ-UY,剑指苍穹, 1708300800000, Math.floor(Math.random() * 6), Math.floor(Math.random() * 100),白嫖ChatGPT4的功能。然后抱着试一试的态度把玩了一下。发现真的好用。, false),new CommentData(https://fastly.picsum.photos/id/439/600/600.jpg?hmacLC9k_bzrN0NhKRyV62fou3ix3cRFZKNfAyXgxGs6zh8,黑暗王国, 1708646400000, Math.floor(Math.random() * 6), Math.floor(Math.random() * 100), 字数越少事情越大。,false),]return result
}