Skip to content

Commit

Permalink
feat(web-renderer): add web-renderer demo & docs (#2234)
Browse files Browse the repository at this point in the history
* docs(web-renderer): add web-renderer docs

* docs(web-renderer): add web-renderer docs

* feat(hippy-react-demo): Support for hippy web renderer

* refactor(hippy-react-demo): Remove unnecessary code

* refactor(hippy-react-demo): update package version 0.1.0

* refactor(hippy-react-demo): update package and comments

* feat(hippy-vue-demo): Support for hippy web renderer

* feat(hippy-react-demo): Fixed web renderer package

* docs(web-renderer): update integration

* chore(hippy-web-renderer): Patch webpack conifg for hippy web renderer

* chore(hippy-web-renderer): Patch webpack conifg for hippy web renderer

* docs(hippy-web-renderer): Update markdown for hippy web renderer

* docs(hippy-web-renderer): Update markdown and package.json

* docs(hippy-web-renderer): Update doc and package.json for web-renderer

* docs(hippy-web-renderer): Update doc and package.json for web-renderer

Co-authored-by: mingwwang <mingwwang@tencent.com>
Co-authored-by: Zoom Chan <zoom_chan@163.com>
  • Loading branch information
3 people committed Jul 25, 2022
1 parent 10276ab commit ca39aea
Show file tree
Hide file tree
Showing 17 changed files with 1,071 additions and 4 deletions.
8 changes: 7 additions & 1 deletion docs/_navbar.md
Expand Up @@ -29,7 +29,13 @@
* [定制适配器](ios/custom-adapter.md)
* [定制界面组件](ios/custom-component.md)
* [定制模块](ios/custom-module.md)


* Web
* [Web 集成](web/integration.md)
* [Web 事件](web/event.md)
* [定制界面组件](web/custom-component.md)
* [定制模块](web/custom-module.md)

* Hippy-React
* [介绍](hippy-react/introduction.md)
* [组件](hippy-react/components.md)
Expand Down
1 change: 1 addition & 0 deletions docs/_sidebar.md
Expand Up @@ -4,6 +4,7 @@
* [开始接入](guide/integration.md)
* [Android](android/integration.md)
* [iOS](ios/integration.md)
* [Web](web/integration.md)
* [Hippy-React](hippy-react/introduction.md)
* [Hippy-Vue](hippy-vue/introduction.md)
* [样式](style/layout.md)
6 changes: 6 additions & 0 deletions docs/web/_sidebar.md
@@ -0,0 +1,6 @@
<!-- docs/android/_sidebar.md -->

* [Web 集成](web/integration.md)
* [前端事件](web/event.md)
* [定制组件](web/custom-component.md)
* [定制模块](web/custom-module.md)
158 changes: 158 additions & 0 deletions docs/web/custom-component.md
@@ -0,0 +1,158 @@
# Hippy Web Renderer 自定义组件

Hippy开发过程中可能有很多场景使用当前的能力是无法满足的,这就需要对UI组件封转或者引入一些三方的功能来完成需求。

# 组件的扩展

接下来将以CustomView为例,从头介绍如何扩展组件。

扩展组件包括:

*扩展 `HippyView`

*实现 实现构造方法。

*实现 设置自定义组件的`tagName`

*实现 构造自定义组件的`dom`

*实现 自定义组件的`api能力`

*实现 自定义组件的属性。

# 扩展 HippyView

HippyView类,实现了一些HippyBaseView的接口和属性定义。在一个自定义组件中有几个比较重要的属性:

* id:每一个实例化component的唯一标识,默认会赋值给组件的dom的id属性

* pId:每一个实例化component的父组件标识

* tagName:是用来区分组件的类型,也是业务侧代码使用该组件时在nativeName属性上填写的值,用来关联自定义组件的key

* dom:真正挂载到document上的节点

* props:承载了从业务侧传递过来的属性和style的记录

下面这个例子中,我们创建了CustomView自定义组件,用来显示一个视频。

第一步:

继承自`HippyView`

实现构造方法。

设置自定义组件的`tagName``CustomView`,这样业务侧使用的时候就可以设置`nativeName="CustomView"`进行关联。

构造自定义组件的dom,我们创建了一个video节点并赋值给dom成员变量。注意dom成员变量在构造方法结束前一定要设置上。

```javascript

import { HippyView, HippyWebEngine, HippyWebModule } from '@hippy/web-renderer';

class CustomView extends HippyView {
constructor(context,id,pId) {
super(context,id,pId);
this.tagName = 'CustomView';
this.dom = document.createElement('video');
}
}

```

第二步:

实现自定义组件的api能力

实现自定义组件的属性

```javascript

import { HippyView, HippyWebEngine, HippyWebModule } from '@hippy/web-renderer';

class CustomView extends HippyView {

set src(value){
this.dom.src = value;
}

get src(){
return this.props['src'];
}

play(){
this.dom.play();
}

pause(){
this.dom.pause();
this.context.sendUiEvent(this.id,'onPause',{});
}
}

```

上面这个例子中 :

我们为`CustomView`实现了一个属性`src`,当业务侧修改src属性当时候就会触发`set src()`方法并且获取到变更后的value。

我们还实现了组件的两个方法`play``pause`,当业务侧使用 `callUIFunction(this.instance, 'play'/'pause', []);`调用时就可以调用到这两个方法。

`pause()`方法中,我们使用`sendUiEvent`向业务侧发送了一个`onPause`事件,业务侧的`onPause`属性上设置的回调就会被触发。

>关于`props`
>
>&emsp; `HippyWebRenderer`底层默认会将业务侧传递过来的原始`props`存储到组件到`props`属性上,然后针对更新的`prop`项逐个调用与之对应的key的set方法,来让组件获得一个更新时机,从而进行一些行为。
>
>&emsp; `props`里面有一个对象`style`,承载了所有业务侧设置的样式。默认也是由`HippyWebRenderer`设置到自定义组件到`dom`上,中间其实会有一层转换,因为`style`中的有一些值是`hippy`特有的,需要进行一次翻译才可以设置到`dom``style`上。
>
>关于`context`:
>
>自定义组件被构造的时候会传入一个`context`,它提供了一些关键的方法:
```javascript
export interface ComponentContext {
sendEvent: (type: string, params: any) => void;//向业务侧发送全局事件
sendUiEvent: (id: number, type: string, params: any) => void;//向某个组件实例发送事件
sendGestureEvent: (e: HippyTransferData.NativeGestureEvent) => void;//发送手势事件
subscribe: (evt: string, callback: Function) => void;//订阅某个事件
getModuleByName: (moduleName: string) => any;//获取模块实例,通过模块名
}
```

# 复杂组件

有的时候我们可能需要提供一个容器,用来装载一些已有的组件。而这个容器有一些特殊的形态或者行为,比如需要自己管理子节点插入和移除,或者修改样式和拦截属性等。那么这个时候就需要使用一些复杂的组件实现方式。

关于组件自己实现子节点的dom插入和删除,`HippyWebRender`默认的组件`dom`插入和删除,是使用Web的方法:

```javascript
Node.insertBefore<T extends Node>(node: T, child: Node | null): T;
Node.removeChild<T extends Node>(child: T): T;
```

如果组件不希望以这种默认的形式来实现就需要自己实现,`insertChild``removeChild`方法自己管理节点的插入和移除逻辑。

```javascript
class CustomView extends HippyView{
insertChild (child: HippyBaseView, childPosition: number){
...
}
removeChild (child: HippyBaseView){
...
}
}
```

关于组件`props`更新的拦截,需要实现组件的`updateProps方法`

```javascript
class CustomView extends HippyView{

updateProps (data: UIProps, defaultProcess: (component: HippyBaseView, data: UIProps) => void){
...
}
}
```

上面的例子中,`data`是组件本次更新的`props`数据信息,`defaultProcess()``HippyWebRenderer`默认处理`props`更新的方法,开发者可以在这里拦截修改更新的数据后,依然使用默认的props更新方法进行更新,也可以不用默认的方法自行进行属性更新的遍历和操作。
63 changes: 63 additions & 0 deletions docs/web/custom-module.md
@@ -0,0 +1,63 @@
# Hippy Web Renderer 自定义模块

Hippy开发过程中可能有很多场景使用当前的能力是无法满足的,可能就需要使用三方库来提供一下额外的能力或者需要提供模块对齐终端的能力。这就涉及到如何提供一个自定义模块

# 模块的扩展

接下来将以CustomModule为例,从头介绍如何扩展Module。

扩展模块包括:

* 创建`HippyWebModule`的子类。

* 设置`Moduel``name`属性。

* 实现`Module`需要暴露给前端的`api`

# 扩展HippyWebModule

`HippyWebModule`类,标准化了HippyWebRenderer可使用的模块。提供了一些HippyWebRenderer的上下文。在一个自定义组件中有几个比较重要的属性:

* name:定义了模块的名字,也是跟前端侧使用`callNative(moduleName,methodName)`中的moduleName相映射的
* context:提供了一系列的方法

```javascript
sendEvent(type: string, params: any);//发送事件
sendUiEvent(nodeId: number, type: string, params: any);//发送ui相关事件
sendGestureEvent(e: HippyTransferData.NativeGestureEvent);//发送手势事件
subscribe(evt: string, callback: Function);//监听某个事件
getModuleByName(moduleName: string);//使用模块名获取模块
```

下面这个例子中,我们创建了CustomModule,用来提供一个获取浏览器信息。

第一步:
继承自HippyWebModule。

第二步:
设置Module的name属性。

第三步:
实现API,`getBrowserInfo``setBrowserTitle`分别提供了获取当前浏览器的信息和设置浏览器title的功能。在提供自定义模块的api时,api的参数为`function name(arg1,arg2...argn,callBack)`,前面的n个参数对应业务侧调用时的传递参数,最后一个`callback`是当业务侧以需要返回值的形式进行调用时,提供的返回结果的回调。

```javascript
import { HippyWebModule } from '@hippy/web-renderer';
export class CustomModule extends HippyWebModule {
name = 'CustomModule';

getBrowserInfo(callBack){
let data = {};
...
callBack.resolve(data);
}

setBrowserTitle(title,callBack){
if(title) {
window.document.title = title;
}
...
callBack.resolve(true);
//callBack.reject(null);执行失败时
}
}
```
44 changes: 44 additions & 0 deletions docs/web/event.md
@@ -0,0 +1,44 @@
# 前端事件

当浏览器加载结束或者使用了一些三方库完成一些功能后需要向业务侧抛出事件。

# 前端发送

前端在需要发送事件的地方调用代码:

## 在模块中

发送事件,`HippyWebModule`基类提供的`context`提供了向业务层发送事件的能力

```javascript
const eventName = '自定义名字';
const param = {};
context.sendEvent(eventName, param);
```

## 在component中

发送事件,`HippyWebView`基类提供的`context`提供了向业务层发送事件的能力

```javascript
const eventName = '自定义名字';
const param = {};
context.sendEvent(eventName, param);
```

## 在全局中

发送事件,`Hippy.web.engine`提供的`context`提供了向业务层发送事件的能力

```javascript
const engine = Hippy.web.engine;
const eventName = '自定义名字';
const param = {};
engine.context.sendEvent(eventName, param);
```

# 前端业务监听事件

[hippy-react监听事件](hippy-react/native-event.md?id=事件监听器)

[hippy-vue监听事件](hippy-vue/native-event.md?id=事件监听器)

0 comments on commit ca39aea

Please sign in to comment.