使用宿主平台数据
Lynx 允许宿主平台在页面加载时提供一份初始数据,并且在之后随时对这些数据进行更新。
这份初始数据被称为 initData
。
提供和更新数据
前置步骤
你需要完成接入现有应用中的指引,以确保你的应用已经集成了 Lynx,并对 Lynx 的 Native API 有基本的了解。
在使用 LynxView.loadTemplate()
加载一个 Bundle 的时候,你有机会传入一些数据:
LynxLoadMeta* meta = [LynxLoadMeta init];
// meta.url = @"";
// meta.binaryData = nil;
// meta.templateBundle = nil;
meta.initialData = __YOUR_DATA__;
// meta.loadOption = LynxLoadOptionDumpElement | LynxLoadOptionRecycleTemplateBundle;
[lynxView loadTemplate:meta];
LynxLoadMeta.Builder builder = new LynxLoadMeta.Builder();
// builder.setUrl();
// builder.setBinaryData();
// builder.setTemplateBundle();
builder.setInitialData(__YOUR_DATA__);
// builder.addLoadOption();
LynxLoadMeta meta = builder.build();
lynxView.loadTemplate(meta);
@Entry
@Component
struct Index {
private metaData: MetaData = new MetaData(new TemplateData(__YOUR_DATA__));
build() {
Column() {
LynxView({
// url: this.url,
// buffer: this.buffer,
metadata: this.metaData,
}).width('100%').height('100%');
}
.size({ width: '100%', height: '100%' })
}
}
你可以在后续需要的时机通过 LynxView.updateData()
(或 HarmonyOS 平台的 LynxContext.updateData()
) 来更新这些数据:
LynxUpdateMeta* meta = [LynxUpdateMeta init];
meta.data = __YOUR_DATA__;
[lynxView updateData:meta];
LynxUpdateMeta.Builder builder = new LynxUpdateMeta.Builder();
builder.setUpdatedData(__YOUR_DATA__);
LynxUpdateMeta meta = builder.build();
lynxView.updateMetaData(meta);
@Entry
@Component
struct Index {
private metaData: MetaData = new MetaData(new TemplateData(__YOUR_DATA__));
private context?: LynxContext;
build() {
Column() {
LynxView({
// url: this.url,
// buffer: this.buffer,
metadata: this.metaData,
onCreate: (context: LynxContext) => {
this.context = context;
this.context.updateMetaData(new MetaData(new TemplateData(__YOUR_DATA__)));
}
}).width('100%').height('100%');
}
.size({ width: '100%', height: '100%' })
}
}
你在加载时传入的数据和后续更新时传入的数据都可以在前端使用,下面是如何在前端使用这些数据。
使用数据
前端可以通过 useInitData()
来获取 initData
。
在宿主平台更新数据时,这些组件会自动重新渲染。
src/App.jsx
import { useInitData } from '@lynx-js/react';
function App() {
const initData = useInitData();
return (
<view>
<text>{initData.greeting}</text>
</view>
);
}
如果你使用传统的类组件,那么可以使用 InitDataConsumer
。
import { Component, InitDataProvider, InitDataConsumer } from '@lynx-js/react';
class C extends Component {
render() {
return (
<InitDataConsumer>
{(initData) => (
<view>
<text>{initData.greeting}</text>
</view>
)}
</InitDataConsumer>
);
}
}
注意 InitDataConsumer
必须作为 InitDataProvider
的子节点使用。
<InitDataProvider>
<view>
<C />
</view>
</InitDataProvider>
使用数据前进行预处理
虽然 useInitData()
会从宿主平台为你提供 initData
,但它可能不是你期望的格式。
想象一下,你有以下混乱的 initData
:
-
在 Android 或 HarmonyOS 上:
{
"pageTitle": "Hello Lynx"
}
-
但是,在 iOS 上:
{
"page_title": "Hello Lynx"
}
如果你想要兼容这些平台,你的代码可能会变得不那么干净:
import { useInitData } from '@lynx-js/react';
export function App() {
const initData = useInitData();
return (
<view>
<text>{initData.pageTitle || initData.page_title}</text>
</view>
);
}
上述场景只是示例,但 Lynx 确实提供了一种在使用之前处理 initData
的方法,它被称为 dataProcessor
。
使用默认 dataProcessor
如果你(或宿主平台开发人员)没有指定 processorName
,Lynx 将使用 defaultDataProcessor
来处理 initData
。
src/index.tsx
import { root } from '@lynx-js/react';
import { App } from './App.js';
lynx.registerDataProcessors({
defaultDataProcessor: function (rawInitData) {
const { pageTitle, page_title, ...rest } = rawInitData;
return {
...rest,
pageTitle: pageTitle || page_title,
};
},
});
root.render(<App />);
if (import.meta.webpackHot) {
import.meta.webpackHot.accept();
}
然后,在你的组件中,你可以直接使用 initData
:
src/App.jsx
import { useInitData } from '@lynx-js/react';
export function App() {
const initData = useInitData();
return (
<view>
<text>{initData.pageTitle}</text>
</view>
);
}
使用命名的 dataProcessor
你(或宿主平台开发人员)还可以在调用 LynxView.updateData()
(或 HarmonyOS 平台的 LynxContext.updateData()
) 时指定 processorName
:
LynxUpdateMeta *meta = [[LynxUpdateMeta alloc] init];
[lynxView updateData:meta];
LynxUpdateMeta meta = new LynxUpdateMeta();
lynxView.updateMetaData(meta);
@Entry
@Component
struct Index {
private metaData: MetaData = new MetaData(new TemplateData(__YOUR_DATA__));
private context?: LynxContext;
build() {
Column() {
LynxView({
// url: this.url,
// buffer: this.buffer,
metadata: this.metaData,
onCreate: (context: LynxContext) => {
const templateData: TemplateData = new TemplateData('', 'someDataProcessor');
this.context = context;
this.context.updateMetaData(new MetaData(templateData));
}
}).width('100%').height('100%');
}
.size({ width: '100%', height: '100%' })
}
}
因此,你定义的一个命名的 dataProcessor
将被调用来处理 initData
,你可以使用以下语法定义多个 dataProcessor
:
src/index.tsx
import { root } from '@lynx-js/react';
import { App } from './App.js';
lynx.registerDataProcessors({
dataProcessors: {
someDataProcessor: function (rawInitData) {
// process rawInitData
returnprocessedInitData;
},
anotherDataProcessor: function (rawInitData) {
// process rawInitData
returnprocessedInitData;
},
},
});
root.render(<App />);
if (import.meta.webpackHot) {
import.meta.webpackHot.accept();
}
如果业务逻辑需要,这允许你(或宿主平台开发人员)在宿主平台上决定使用哪个 dataProcessor
。