美文网首页
知乎案例-ObjectLink

知乎案例-ObjectLink

作者: 家乡的蝈蝈 | 来源:发表于2024-01-31 11:30 被阅读0次
@Entry
@Component
struct ObjectLinkZhiHu {
  @State commentList: ReplyItemClass[] = [
    new ReplyClass({
      id: 1,
      avatar: 'https://picx.zhimg.com/027729d02bdf060e24973c3726fea9da_l.jpg?source=06d4cd63',
      author: '偏执狂-妄想家',
      content: '更何况还分到一个摩洛哥[惊喜]',
      time: '11-30',
      area: '海南',
      likeNum: 34
    }),
    new ReplyClass({
      id: 2,
      avatar: 'https://pic1.zhimg.com/v2-5a3f5190369ae59c12bee33abfe0c5cc_xl.jpg?source=32738c0c',
      author: 'William',
      content: '当年希腊可是把1:0发挥到极致了',
      time: '11-29',
      area: '北京',
      likeNum: 58
    }),
    new ReplyClass({
      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
    }),
    new ReplyClass({
      id: 4,
      avatar: 'https://picx.zhimg.com/v2-53e7cf84228e26f419d924c2bf8d5d70_l.jpg?source=06d4cd63',
      author: '正宗好鱼头',
      content: '确实眼红啊,亚洲就没这种球队,让中国队刷',
      time: '11-27',
      area: '香港',
      likeNum: 139
    }),
    new ReplyClass({
      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
    }),
    new ReplyClass({
      id: 6,
      avatar: 'https://picx.zhimg.com/v2-fab3da929232ae911e92bf8137d11f3a_l.jpg?source=06d4cd63',
      author: '飞轩逸',
      content: '禁止欧洲杯扩军之前,应该先禁止世界杯扩军,或者至少把亚洲名额一半给欧洲。',
      time: '11-26',
      area: '里约',
      likeNum: 100
    })
  ]
  changeLike(obj:ReplyItemClass) {
    if (obj.likeFlag) {
      obj.likeFlag = false
      obj.likeNum--
    } else {
      obj.likeFlag = true
      obj.likeNum++
    }
    // State数据只能监听到第一层的变化
    // 怎么让数据具备驱动型
    const index = this.commentList.findIndex(item => item.id === obj.id)
    // this.commentList[index] = {...obj} // 禁用延展运算符,next不支持
    this.commentList.splice(index,1,obj) // splice表示从哪个位置删除,删除几个,使用obj来替换
  }
  addComment(item:ReplyItemClass) {
    this.commentList.unshift(item) // 在数组的头部添加元素
  }
  build() {
    Stack({alignContent:Alignment.Bottom}) {
      Scroll() { //只能放置一个子组件
        Column() {
          NavBar()
          CommentItem({
            item: {
              id: 1,
              avatar: $r('app.media.icon'),
              author: '周杰伦',
              content: '意大利拌面应该使用42号钢筋混凝土再加上量子力学缠绕最后通过不畏浮云遮望眼',
              time: '11-30',
              area: '海南',
              likeNum: 100
            }
          })
          // 分割线
          Divider()
            .strokeWidth(6)
            .color("#f4f4f4")
          Row() {
            Text("回复7")
              .width('100%')
              .fontWeight(FontWeight.Bold)
          }.height(40).padding({left:20})
          ForEach(this.commentList,(item:ReplyClass) => {
            // CommentItem({item:item}) // 在实例化子组件时,给子组件的属性赋值
            // CommentItem({item}) // 在es6中,当属性和值相同时可以简写
            // CommentItem({item,changLike:this.changeLike.bind(this)}) // 写法错误,
            CommentItem({item:item})

          },(item: ReplyItemClass) => JSON.stringify({ id: item.id, flag: item.likeFlag, num: item.likeNum }))

        }
      }
      .padding({
        bottom:60
      })
      ReplyInput({add: (item:ReplyItemClass) => {
        this.addComment(item)
      }})
    }

  }
}

// 回复评论组件
@Component
struct ReplyInput {
  @State commentStr:string = ""
  // 在回复组件中声明了一个变量add,它的类型是函数,给了一个初始值是函数
  add: (item:ReplyItemClass) => void = () => {}

  build() {
    Row() {
      TextInput({placeholder:'回复~', text:this.commentStr})
        .layoutWeight(1) // 占据除'发布'按钮的所有空间
        .backgroundColor('#4f5f6')
        .onChange((value) => {
          this.commentStr = value
        })
      Text('发布')
        .fontColor('#6ecff6')
        .margin({
          left:10
        })
        .onClick(() => {
          // AlertDialog.show({message:this.commentStr}) // alert弹窗
          // 告诉父组件,我拿到值,你给我个方法我来调一下
          // 要传入一个新的评论对象
          if (this.commentStr !== "") {
            let obj:ReplyItemClass = {
              id: Date.now(),
              content: this.commentStr,
              avatar: $r("app.media.icon"),
              likeNum:0,
              likeFlag:false,
              author:"高大的绿地",
              time:`${ new Date().getMonth() + 1}-${ new Date().getDate()}`,
              area:'上海'
            }
            this.add(obj)
            this.commentStr = ""
          }
        })
    }
      .border({
        color:'#f4f5f6',
        width: {
          top:1
        }
      })
      .height(50)
      .backgroundColor(Color.White)
      .width('100%')
      .padding({
        left:10,
        right:10
      })
  }
}


@Component
struct NavBar {
  build() {
    Row() {
      Row() {
        Image($r("app.media.ic_public_arrow_left"))
          .fillColor("#848484")
          .width(16)
          .height(16)
      }
      .justifyContent(FlexAlign.Center)
      .width(24)
      .aspectRatio(1)
      .backgroundColor("#f5f5f5")
      .borderRadius(12)
      .margin({
        left:15
      })
      Text("评论回复")
        .layoutWeight(1)
        .textAlign(TextAlign.Center)
        .fontSize(18)
        .padding({
          right:39
        })
    }
    .height(40)
    .border({
      color:"#f4f4f4",
      width:{
        bottom:0.5
      }
    })
  }
}

@Component
struct  CommentItem {
  // 父组件给子组件传参数,在子组件中定义一个属性即可,非响应式数据
  // item:ReplyItem = {id:0,avatar:"",....}
  // 默认public属性
  @ObjectLink
  item:ReplyClass  //Partial是个泛型工具,把类型中的所有属性都变成可选;等价于在类中的属性 id ?: number = 0
  build() {
    Row() {
      Image(this.item.avatar)
        .width(32)
        .aspectRatio(1)
        .borderRadius(16)
      Column({space:10}) {
        Text(this.item.author)
          .fontWeight(FontWeight.Bold)
        Text(this.item.content)
          .fontSize(16)
          .fontColor("#565656")
          .lineHeight(20)
        Row() {
          Text(`${this.item.time} .ip属地${this.item.area}`).fontSize(12).fontColor("#c3c4c5")
          Row() {
            Image($r("app.media.favorite_block"))
              .width(12)
              .aspectRatio(1)
              .fillColor(this.item.likeFlag ? 'red' : '#c3c4c5')
              .margin({
                right:5
              })
            Text(this.item.likeNum?.toString()) // ?表示可选,如果取不到,后面的不执行
              .fontSize(12)
              .fontColor('#c3c4c5')
          }
            .onClick(() => {
              // 点赞
              // this.item属性都是可选的
              if (this.item.likeFlag) {
                this.item.likeFlag = false
                this.item.likeNum--
              } else {
                this.item.likeFlag = true
                this.item.likeNum++
              }
            })
        }.justifyContent(FlexAlign.SpaceBetween)
          .width("100%")
      }
        .alignItems(HorizontalAlign.Start)
        .layoutWeight(1)
        .margin({left:10})
    }.padding(15)
    .alignItems(VerticalAlign.Top)

  }
}

export class ReplyItemClass {
  // next版本在定义属性时需要初始值
  id: number = 0
  avatar: string | Resource = "" // 联合类型,可以是类型中的一个
  author: string = ""
  content: string = ""
  time: string = ""
  area: string = ""
  likeNum: number = 0
  likeFlag?: boolean = false
}

// extends代表继承类,实现父类,也可以调用this.parent()实现父类初始化。而且会覆盖父类定义的变量或者函数,
// implements实现接口,子类不可以覆盖父类的方法或者变量,相同的变量或者函数,会被父类取代掉
@Observed
export class ReplyClass extends ReplyItemClass{
  constructor(obj:ReplyItemClass) {
    super() // 调用父类的构造函数
    this.id = obj.id
    this.avatar = obj.avatar
    this.content = obj.content
    this.time = obj.time
    this.area = obj.area
    this.likeNum = obj.likeNum
    this.likeFlag = obj.likeFlag
  }
}

注意点:

  • ObjectLink只能修饰被Observed修饰的class类型
  • Observed修饰的class的数据如果是复杂数据类型,需要采用赋值的方式才可以具备响应式特性-因为它监听的是该属性的set和get
  • 如果出现复杂类型嵌套,只需要Observed我们需要的class即可,至于用于类型的class可以用type或者interface

相关文章

网友评论

      本文标题:知乎案例-ObjectLink

      本文链接:https://www.haomeiwen.com/subject/cekoodtx.html