实战14-搜索栏组件化02

@Observed
export class BannerListDataSource implements IDataSource {
  //内不用来触发ui更新对象
  listeners: DataChangeListener[] = []
  //用来管理数据
  bannerList: IBannerList = []

  //实现了IDataSource接口
  //接口需要必须定义四个方法:getData totalCount registerDataChangeListener unregisterDataChangeListener
  //读取对应下标的数据
  getData(index: number): IBannerItem {
    return this.bannerList[index]
  }

  //返回数据总长度
  totalCount(): number {
    return this.bannerList.length

  }

  //保存单个数据
  setData(item: IBannerItem) {
    //只会更新数据,不会更新ui
    this.bannerList.push(item);
    //更新ui
    this.notifyDataAdd(this.bannerList.length - 1)
  }

  //更新所有数据
  setList(list: IBannerList) {
    this.bannerList = list;
    this.notifyDataReload();
  }

  // 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听
  registerDataChangeListener(listener: DataChangeListener): void {
    if (this.listeners.indexOf(listener) < 0) {
      console.info('add listener');
      this.listeners.push(listener);
    }
  }

  // 该方法为框架侧调用,为对应的LazyForEach组件在数据源处去除listener监听
  unregisterDataChangeListener(listener: DataChangeListener): void {
    const pos = this.listeners.indexOf(listener);
    if (pos >= 0) {
      console.info('remove listener');
      this.listeners.splice(pos, 1);
    }
  }

  // 通知LazyForEach组件需要重载所有子组件
  notifyDataReload(): void {
    this.listeners.forEach(listener => {
      listener.onDataReloaded();
    })
  }

  // 通知LazyForEach组件需要在index对应索引处添加子组件
  notifyDataAdd(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataAdd(index);
    })
  }

  // 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件
  notifyDataChange(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataChange(index);
    })
  }

  // 通知LazyForEach组件需要在index对应索引处删除该子组件
  notifyDataDelete(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataDelete(index);
    })
  }

  // 通知LazyForEach组件将from索引和to索引处的子组件进行交换
  notifyDataMove(from: number, to: number): void {
    this.listeners.forEach(listener => {
      listener.onDataMove(from, to);
    })
  }
}

export interface HomeData {
  "bannerList": IBannerList
  "navList": INavList
  "titleList": ITitleList
  "planList": IPlanList
  "adPicTure": string
}

export interface IBannerItem {
  "id": number,
  "name": string,
  "imageURL": string
}

export type IBannerList = IBannerItem[]

export interface INavItem {
  "id": number,
  "title": string,
  "imageURL": string
}

export type INavList = INavItem[]

export interface ITitleItem {
  "id": number
  "imageURL": string
  "title": string
  "sub_title": string
}

export type ITitleList = ITitleItem[]

export interface IPlanItem {
  "id": number
  "imageURL": string
}

export type IPlanList = IPlanItem[]


export interface ITagItem {
  name: string
}

export type ITagList = ITagItem[]


export interface IColor {
  bgColor: string;
  fontColor: string
}


//推荐房源接口getRoomRecommendListApi
export interface IRoomRecommendItem {
  "id": string
  "housePicture": string
  "tags": ITagList
  "houseTitle": string
  "address": string
  "renPriceUnit": string
  "renPriceListing": string
  "rentArea": string
}

export type IRoomRecommendList = IRoomRecommendItem[]

export class RoomRecommendDateSource implements IDataSource {
  //内不用来触发ui更新对象
  listeners: DataChangeListener[] = []
  roomRecommendList: IRoomRecommendList = []

  // 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听
  registerDataChangeListener(listener: DataChangeListener): void {
    if (this.listeners.indexOf(listener) < 0) {
      console.info('add listener');
      this.listeners.push(listener);
    }
  }

  // 该方法为框架侧调用,为对应的LazyForEach组件在数据源处去除listener监听
  unregisterDataChangeListener(listener: DataChangeListener): void {
    const pos = this.listeners.indexOf(listener);
    if (pos >= 0) {
      console.info('remove listener');
      this.listeners.splice(pos, 1);
    }
  }

  getData(index: number) {
    return this.roomRecommendList[index]
  }

  totalCount(): number {
    return this.roomRecommendList.length
  }

  setList(list: IRoomRecommendList) {
    this.roomRecommendList = list;
    this.notifyDataReload();
  }

  // 通知LazyForEach组件需要重载所有子组件
  notifyDataReload(): void {
    this.listeners.forEach(listener => {
      listener.onDataReloaded();
    })
  }
}
import { IColor } from '../../api/models/HomeData';

@Component
export default struct ScrollContainer {
  @BuilderParam contentBuilder: () => void = this.defaultBuilder
  @BuilderParam navBuilder: ($$: IColor) => void = this.defaultBuilder
  scrollY: number = 0;
  @State bgColor: string = 'rgba(255, 255, 255, 0)'
  @State fontColor: string = 'rgb(255, 255, 255)'

  @Builder
  defaultBuilder() {
  }

  // 处理滚动
  handleScroll = (scrollX: number, scrollY: number) => {
    // 更新并修正 scrollY 的值
    this.scrollY += scrollY;
    if (this.scrollY < 0) {
      this.scrollY = 0
    }
    this.calcColor();
  }
  // 计算颜色
  calcColor = () => {
    if (this.scrollY > 10) {
      this.bgColor = 'rgba(255, 255, 255, 1)'
      this.fontColor = 'rgb(0, 0, 0)'
    } else {
      this.bgColor = 'rgba(255, 255, 255, 0)'
      this.fontColor = 'rgb(255, 255, 255)'
    }
  }

  build() {
    Stack() {
      Scroll() {
        Column() {
          // 渲染内容
          this.contentBuilder()
        }.align(Alignment.TopStart)
      }
      .height('100%')
      .scrollBar(BarState.Off)
      .align(Alignment.TopStart)
      .backgroundColor($r('app.color.bg_gray_second'))
      .padding({ bottom: 10 })
      .onDidScroll(this.handleScroll)

      Column() {
        // 渲染头部导航
        this.navBuilder({ fontColor: this.fontColor, bgColor: this.bgColor })
      }.backgroundColor(this.bgColor)

    }.height('100%').alignContent(Alignment.TopStart)
  }
}

 

import { getHomeDataApi } from '../api/home';
import { BannerListDataSource, IColor, INavList, IPlanList, ITitleList } from '../api/models/HomeData';
import SwiperLayout from '../views/Home/SwiperLayout';
import { window } from '@kit.ArkUI';
import NavList from '../views/Home/NavList';
import { PADDING, SHADOW_RADIUS } from '../constants/size';
import SearchBar from '../views/Home/SearchBar';
import TitleList from '../views/Home/TitleList';
import PlanList from '../views/Home/PlanList';
import RoomRecommend from '../views/Home/RoomRecommend';
import ScrollContainer from '../components/ScrollContainer/Index';


@Component
export default struct Home {
  @State bannerList: BannerListDataSource = new BannerListDataSource()
  @State navList: INavList = []
  @State titleList: ITitleList = []
  @State planList: IPlanList = []
  @State adPicure: string = ''
  //获取首页数据的函数
  getHomeData = async () => {
    const result = await getHomeDataApi()
    this.bannerList.setList(result.bannerList)
    this.navList = result.navList;
    this.titleList = result.titleList;
    this.planList = result.planList;
    this.adPicure = result.adPicTure;

  }

  //生命周期函数:初始化渲染时候
  aboutToAppear(): void {
    this.getHomeData()

    window.getLastWindow(getContext())
      .then(win => {
        win.setWindowLayoutFullScreen(true)
      })
  }

  @Builder
  navBuilder($$: IColor) {
    //搜索区
    SearchBar({ bgColor: $$.bgColor, fontColor: $$.fontColor })
  }

  @Builder
  contentBuilder() {
    //Builder函数this指向默认是undefined
    //轮播图组件
    SwiperLayout({ bannerList: this.bannerList })
    Column() {
      //导航栏
      NavList({ navList: this.navList })
      // TitleList
      TitleList({ titleList: this.titleList })
      //计划列表
      PlanList({ planList: this.planList })
      //广告
      Image(this.adPicure)
        .width('100%')
        .height(60)
        .objectFit(ImageFit.Fill)
        .shadow(
          {
            offsetX: 0,
            offsetY: 0,
            radius: SHADOW_RADIUS,
            color: 'rgba(0,0,0.14)'
          }
        )
        .margin({ top: 10 })
    }.padding({ left: PADDING, right: PADDING })

    //房源推荐
    RoomRecommend()
  }

  build() {
    ScrollContainer({
      contentBuilder: () => {
        this.contentBuilder()
      },
      navBuilder: this.navBuilder
    })
  }
}

 

1.Builder 和 BuildParam的区别?
Builder是当前组件的UI复用结构, BuilderParams是接收父组件传入的UI复用结构, 传过来的类型是UI复用结构类型。

Builder传值,想要响应式必须是对象,如果是基础数据类型,不具备响应式。

Builder的传值有基础类型传值和引用类型传值,引用类型传值才能具备响应式的特点

BuilderParam中有一种尾随闭包的写法,就是组件( )后面的大括号可以传入内容,有两个前提 1.必须只有一个BuilderParam 2. BuilderParam没有接收参数的需求才可以


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值