复杂组件(JSCore & Webview)

在某些场景里,可能需要处理自定义的手势操作或者复杂的 UI 交互,这个时候不仅需要编写 JSCore 中的业务逻辑,还需要处理 webview 中的交互逻辑。下面我们来看看如何写这样一个组件

组件创建

所有的 复杂组件 都需要放到指定位置:项目目录/src/components 中。这是因为,JSCore 中的代码和 webview 中的代码是分开打包的,只有放在这个目录中的特定文件才会被打包到 webview 代码中。

src
├── components
│   ├── test
│   │   ├── browser.js
│   │   ├── index.js
│   │   └── main.css
...

在 components 下的组件目录中,必须至少包含:index.js 和 browser.js。其中,index.js 是 JSCore 中的组件代码,browser.js 是 webview 中的组件代码。

我们在 JSCore 和 webview 中都实现了组件的对应逻辑,然后将两个组件进行关联来实现复杂的功能。为了区分,我们将 JSCore 中的称为 Component,将 webview 中的称为 UIComponent。

Component(index.js)

index.js 中的 Component 与一个简单组件的代码区别不大,就是类似 React 组件的写法。

唯一需要注意的是,你需要为你的组件设置一个唯一标识。 只有有了这个标识,JSCore 和 webview 重的代码才能同时映射到对应的组件上。通过添加 displayName 来添加这个标识。

代码节选自:/src/componets/test/index.js
import { Component } from "@qnpm/yis";

export default class Test extends Component {
    displayName = "Test";
    constructor() {}
    render() {}
}

UIComponent(browser.js)

browser.js 是运行在 webview 中的组件代码,用来处理 UI 逻辑。

在 webview 中,我们并没有提供 React,所以你需要写原生 JS 代码。为了方便构建 UIComponent,我们提供了类似 React.Component 的基类 UIComponent,也提供了 UIComponent 的生命周期。生命周期相关的逻辑可以参考 组件运行机制

此外,你还需要通过 @YISComponent.UI('组件标识') 来与 JSCore 中的组件进行关联,此处的组件标识即为 JSCore 代码中的 displayName。

代码节选自:/src/componets/test/browser.js
import { UIComponent } from '@qnpm/yis';

@YISComponent.UI('Test')
export default class Test extends UIComponent {
    constructor(props) { }
    componentWillMount({vnode}) { }
    componentDidMount({props, vnode}) { }
    componentWillUpdate({nextProps, vnode}) { }
    componentDidUpdate({props, vnode}) { }
    componentWillUnmount({vnode}) { }
}

与 React.Component 中略有不同的是,UIComponent 并不需要提供 render 方法,因为 UIComponent 是按照 JSCore 中的 render 产生的虚拟 dom 树来进行 render 的。只是在对应的节点加载和更新的时候触发对应的生命周期回调。这些生命周期函数的详细信息可以参考 组件生命周期



接下来我们将要重点介绍 Component 和 UIComponent 是如何关联工作的。前面已经说到了,Component 和 UIComponent 必须有同样的标识,才能自动进行关联。除此之外,我们需要关注的还有:属性的传递、事件的传递。