@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没有接收参数的需求才可以