该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

node_pool

专门为OpenHarmony打造的一款全局自定义组件复用的三方库,致力于更高效、更轻便、更简单。

简介

通过BuilderNode创建全局的自定义组件复用池,实现跨页面的组件复用。

效果展示

预览图

安装教程

ohpm install @hadss/nodepool

使用说明

创建可复用的自定义组件

import { NodeItem, CustomNodePoolFactory } from '@hadss/nodepool';

class Params {
  text: string = "this is a text";

  constructor(text: string) {
    this.text = text;
  }
}

@Builder
function ButtonBuilder(params: Params) {
  Column() {
    Button(`button ` + params.text)
      .borderWidth(2)
      .backgroundColor(Color.Orange)
      .width("100%")
      .height("100%")
      .gesture(
        TapGesture()
          .onAction((event: GestureEvent) => {
            console.log("TapGesture");
          })
      )
  }
  .width('100%')
  .height(300)
  .backgroundColor(Color.Gray)
}

创建Builder及复用池类型

let btnBuilder: WrappedBuilder<ESObject> = wrapBuilder<ESObject>(ButtonBuilder);

const REUSE_VIEW_TYPE_SWIPER: string = 'reuse_type_swiper_';

创建一个CustomNodePoolFactory类型的对象,通过多例模式预创建NodePool复用池,同时通过单例模式获取创建NodePool组件复用池,根据传入的type类型查找复用池中是否存在可复用的组件,如果有则直接使用,如果没有则重新创建。使用NodeContainerProxy组件占位,从复用池NodePool中获取组件加载到页面中

@Entry
@Component
struct Index {
  private nodePoolFactory: CustomNodePoolFactory = new CustomNodePoolFactory();
  private controller: NodeItem | undefined;
  private typeCfg: TypeReuseConfig = {
    type: REUSE_VIEW_TYPE_SWIPER,
    expirationTime: 30 * 60 * 1000, // 老化时间
    reuseCallback: this.reuseCallback,
    recycleCallback: this.recycleCallback
  }

  // 组件复用生命周期回调
  private reuseCallback(item: NodeItem): void {
    console.log('tag1', `reuseCallback, id:${item.id}`);
  }

  // 组件回收生命周期回调
  private recycleCallback(item: NodeItem): void {
    console.log('tag1', `recycleCallback, id:${item.id}`);
  }

  aboutToAppear(): void {
    this.nodePoolFactory.getCommonNodePool().setTypeReuseConfig(this.typeCfg);
    // 组件复用
    this.controller = this.nodePoolFactory.getCommonNodePool().getNode(REUSE_VIEW_TYPE_SWIPER, {
      text: 'hello'
    }, btnBuilder);
  }

  build() {
    Column() {
      NodeContainerProxy({ nodeItem: this.controller })
      Text("点我进行参数传递和触摸事件传递")
        .width('100%')
        .height(300)
        .backgroundColor(Color.Pink)
        .onTouch((event) => {
          if (event != undefined) {
            this.controller?.postTouchEvent(event); // 触摸事件传递
            this.controller?.node?.update(new Params("on update data")); // 参数传递
          }
        })
    }
  }
}

接口说明

NodeContainerProxy组件

参数名称 入参内容 功能简介
nodeItem NodeItem, undefined 节点Controller

CustomNodePoolFactory接口

接口名称 入参内容 功能简介
getCommonNodePool NA 获取单例节点池
getNodePool NodePoolConfig 获取多例节点池

NodePoolConfig参数列表

参数名称 入参内容 功能简介
typeCount number 节点种类数量,默认值:50
nodeSize number 某种节点数量,默认值:100
expirationTime number 老化时间,默认值:24小时。单位ms
reuseCallback ReuseCallback 复用时回调函数
recycleCallback RecycleCallback 回收时回调函数

NodePool接口

接口名称 入参内容 功能简介
getNode type: string, data: ESObject, builder: WrappedBuilder 获取节点Controller
getWebNode data: WebData, builder: WrappedBuilder<WebData[]> 获取web节点Controller
preCreateNode type: string, data: ESObject, builder: WrappedBuilder, uiContext: UIContext 预创建节点进池
preCreateWebNode data: WebData, builder: WrappedBuilder<WebData[]>, uiContext: UIContext 预创建web节点进池
setTypeReuseConfig typeCfg: TypeReuseConfig 设置不同类型节点的老化时间
setRecycleCallback recycleCallback: RecycleCallback 设置回收回调
setReuseCallback reuseCallback: ReuseCallback 设置复用回调

注意事项:preCreateNode预创建节点进池需要注意数量限制,如果无限创建会导致节点池爆满

NodePool参数列表

参数名称 入参内容 功能简介
type string 节点种类,可自定义
data ESObject 节点数据
builder WrappedBuilder 创建节点树所需的无状态UI方法@Builder

TypeReuseConfig参数列表

参数名称 入参内容 功能简介
type string 节点种类,可自定义
expirationTime number 老化时间,可自定义
reuseCallback ReuseCallback 组件复用回调函数,可为空
recycleCallback ReuseCallback 组件回收回调函数,可为空

WebData参数列表

参数名称 入参内容 功能简介
url string url地址
controller WebviewController webview控制器
onActive boolean 是否进入前台激活状态,默认值:true
uiContext UIContext UI上下文实例

注意事项:针对组件复用过程中出现的图片闪动(老图片变为新图片的闪动),通过在原始数据中额外增加一个状态变量控制Image组件的渲染, 在三方库预制的recycleCallback和reuseCallback回调中更改这个状态,通知Image组件清空内部缓存数据来解决该问题。
web组件预渲染使用方法
  1. 构建warpBuilder和获取nodepool与上述流程一致
  2. 在web的上级页面进行web页面的预创建(具体页面根据业务场景设定)
      aboutToAppear(): void {
        webData.uiContext = this.getUIContext();
        nodepool.preCreateWebNode(webData, warp);
      }
    
  3. 在web组件页面调用getWebNode获取创建的节点
    item: NodeItem | undefined = nodepool.getWebNode(webData, warp);
    
    Column() {
      NodeContainerProxy({ nodeItem: this.item })
    }
    
  4. 在web组件上开启onActive实现预渲染(只需要预启动效果可不做)
      Web({ src: data.url, controller: data.controller })
        .width('100%')
        .height('100%')
        .onPageBegin(() => {
          if (data.onActive) {
            data.controller.onActive()
          }
        })
    
XComponentWithImage用于解决图片闪动的使用说明
  1. 数据类继承XComponentWithImage
    @Observed
    export class ViewItem extends XComponentWithImage {
      index: number = 0; // 索引
      type: string = ''; // 卡片类型
      title: string = ''; // 标题
      coverImage: Resource | string = ''; // 封面图片
      ...
    }
    
  2. 在提供的两个回调函数中新增是否清除图片的状态
    private reuseCallback(item: NodeItem): void {
        if (item?.data?.item instanceof ViewItem) {
          let newItem: ViewItem = item.data.item as ViewItem;
          newItem.shouldClearImageCache = false;
        }
      }
    
      private recycleCallback(item: NodeItem): void {
        if (item?.data?.item instanceof ViewItem) {
          let newItem: ViewItem = item.data.item as ViewItem;
          newItem.shouldClearImageCache = true;
        }
      }
    
  3. 在图片组件中使用getImageSource方法
    Image(this.item.getImageSource(this.item.coverImage))
    

约束与限制

在下述版本验证通过:
SDK:API12

目录结构

|---- node_pool
|     |---- entry  # 示例代码文件夹
|     |---- nodepool  # nodepool库文件夹
|           |---- index.ets  # 对外接口
│           └--src/main/ets # 框架代码目录
│               ├----constants # 常量目录
│               │
│               ├----lib # 组件复用三方库核心代码目录
│               │
│               ├----model # 各类型图表目录
│               │  
│               └----utils  # 工具类目录
│
└─---- README.md  # 安装使用方法  

参与贡献

使用过程中发现任何问题都可以提 Issue 给我们,当然,我们也非常欢迎你给我们发 PR

开源协议

本项目基于 Apache License 2.0 ,请自由地享受和参与开源。

空文件

简介

创建全局的自定义组件复用池,实现跨页面的组件复用 展开 收起
取消

发行版

暂无发行版

贡献者

全部

近期动态

不能加载更多了
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化