深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
使用说明
- 进入页面即可看到同层渲染效果,Text,search,image都是原生组件。
实现思路
- 添加权限。
“ohos.permission.INTERNET”
- 创建控制器管理绑定的NodeContainer组件。
class SearchNodeController extends NodeController {
private rootNode: BuilderNode<[Params]> | undefined | null;
private embedId : string = “”;
private surfaceId : string = “”;
private renderType :NodeRenderType = NodeRenderType.RENDER_componentTypeDISPLAY;
private componentWidth : number = 0;
private componentHeight : number = 0;
private componentType : string = “”;
setRenderOption(params : NodeControllerParams) {
this.surfaceId = params.surfaceId;
this.renderType = params.renderType;
this.embedId = params.embedId;
this.componentWidth = params.width;
this.componentHeight = params.height;
this.componentType = params.type;
}
/**
- 在对应NodeContainer创建的时候调用、或者通过rebuild方法调用刷新
/
makeNode(uiContext: UIContext): FrameNode | null{
this.rootNode = new BuilderNode(uiContext, { surfaceId: this.surfaceId, type: this.renderType});
if (this.componentType === ‘native/component’) {
this.rootNode.build(wrapBuilder(searchBuilder), { width : this.componentWidth, height : this.componentHeight});
} else {
}
// 返回FrameNode节点
return this.rootNode.getFrameNode();
}
/* - 设置BuilderNode节点
/
setBuilderNode(rootNode: BuilderNode<Params[]> | null): void{
this.rootNode = rootNode;
}
/* - 获取BuilderNode节点
/
getBuilderNode(): BuilderNode<[Params]> | undefined | null{
return this.rootNode;
}
/* - 更新BuilderNode节点
/
updateNode(arg: Object): void {
this.rootNode?.update(arg);
}
/* - 获取EmbedId
/
getEmbedId() : string {
return this.embedId;
}
/* - 将触摸事件派发到rootNode创建出的FrameNode上
*/
postEvent(event: TouchEvent | undefined) : boolean {
return this.rootNode?.postTouchEvent(event) as boolean;
}
}
- 添加同层渲染的组件。
@Component
struct SearchComponent {
@Prop params: Params;
controller: SearchController = new SearchController();
build() {
Column() {
Column({ space: MARGIN_VERTICAL }) {
Text(
r
(
′
a
p
p
.
s
t
r
i
n
g
.
h
e
a
d
l
i
n
e
′
)
)
.
f
o
n
t
S
i
z
e
(
r('app.string.headline')).fontSize(
r(′app.string.headline′)).fontSize(r(‘app.string.ohos_id_text_size_body1’))
Text(
r
(
′
a
p
p
.
s
t
r
i
n
g
.
i
l
l
u
s
t
r
a
t
e
′
)
)
.
f
o
n
t
S
i
z
e
(
r('app.string.illustrate')).fontSize(
r(′app.string.illustrate′)).fontSize(r(‘app.string.ohos_id_text_size_body1’))
}
// 原生Text组件
Text(
r
(
′
a
p
p
.
s
t
r
i
n
g
.
m
a
l
l
′
)
)
.
f
o
n
t
S
i
z
e
(
r('app.string.mall')).fontSize(
r(′app.string.mall′)).fontSize(r(‘app.string.ohos_id_text_size_body1’))
// 原生Search组件
Search({ placeholder: ‘Type to search…’, controller: this.controller })
.searchButton(SEARCH_BUTTON)
// 原生Grid组件,Grid中包含Image和Text
Grid() {
// 性能知识点:此处数据量确定且数量较少,使用了ForEach,在数据量多的情况下,推荐使用LazyForeEach
ForEach(PRODUCT_DATA, (item: ProductDataModel, index: number) => {
GridItem() {
Column({ space: MARGIN_VERTICAL }) {
Image(item.uri).width(KaTeX parse error: Expected '}', got 'EOF' at end of input: …itle).fontSize(r(‘app.string.ohos_id_text_size_body3’))
Text(item.price).fontSize(KaTeX parse error: Expected 'EOF', got '}' at position 42: …_size_body3')) }̲ } } }) } .colu…r(‘app.string.ohos_id_elements_margin_vertical_m’)) // 行间距
.columnsGap($r(‘app.string.ohos_id_elements_margin_vertical_m’)) // 列间距
}
}
}
- embed标签可以在H5页面中嵌入任何类型的内容,在H5界面上通过embed标签标识同层元素,应用侧会将原生组件渲染到H5页面embed标签所在位置。
- 通过WebView的enableNativeEmbedMode()控制同层渲染开关,通过onNativeEmbedLifecycleChange获取embed标签的生命周期变化数据。
build(){
Column() {
Stack() {
// 性能知识点:此处componentId项确定且数量较少,使用了ForEach,在数据量多的情况下,推荐使用LazyForeEach
ForEach(this.componentIdArr, (componentId: string) => {
NodeContainer(this.nodeControllerMap.get(componentId));
}, (embedId: string) => embedId)
// web组件加载本地test.html页面
Web({ src: KaTeX parse error: Expected 'EOF', got '}' at position 61: …rTabController }̲) // 不允许执行缩放 .z…r(‘app.color.ohos_id_color_sub_background’))
}
- h5侧通过id名获取embed标签信息,并通过embed标签添加同层渲染界面的touch监听事件;应用侧添加onNativeEmbedGestureEvent回调使得手指触摸到embed标签时能获取到触摸事件信息。
let nativeEmbed = {
// 通过id名获取embed标签
nativeSearch : document.getElementById(‘nativeSearch’),
// 事件
events:{},
// 初始化
init:function(){
let self = this;
// 添加touch的监听事件
self.nativeSearch.addEventListener(‘touchstart’, self.events, false);
}
};
nativeEmbed.init();
Web({ src: $rawfile(“view.html”), controller: this.browserTabController })
// 获取同层渲染组件触摸事件信息
.onNativeEmbedGestureEvent((touch) => {
this.componentIdArr.forEach((componentId: string) => {
let nodeController = this.nodeControllerMap.get(componentId);
if (nodeController?.getEmbedId() === touch.embedId) {
nodeController?.postEvent(touch.touchEvent);
}
})
})
高性能知识点
ArkWeb同层渲染原生组件,原生组件不仅可以提供H5组件无法实现的一些功能,还能提升用户体验的流畅度;同层渲染节点上下树,实现节点复用,节省节点重复开销。
工程结构&模块类型
nativeembed // har类型
|—mock
| |—GoodsMock.ets // 数据源
|—model
| |—GoodsModel.ets // 数据类
|—view
| |—NativeEmbedView.ets // 视图层
模块依赖
本实例依赖common模块来实现资源的调用。 依赖动态路由模块来实现页面的动态加载。
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
-d2BT0Nkh-1715177558722)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新