weex-html5 扩展开发指引

    xiaoxiao2026-04-22  8

    Weex是一个高可扩展性的跨平台动态化开发方案,你可以在现有组件基础上定制自己需要的三端组件。你可以为Weex API模块添加新的方法,或者创建新的API模块和新的加载器。本文将介绍一些步骤和技巧用于帮助开发者更好的扩展weex-html5的组件,API或者加载器。

    首先要明确的是,组件和API模块是基于weex的扩展,但是独立于weex,组件的定义本身是不需要依赖于weex的,这样有助于组件的分散化管理,去除中心化依赖。

    其次,当你扩展一个组件,你需要同时扩展三端的组件(android, ios和web端),毕竟weex是一个重视三端一致体验的跨平台移动框架。你可以一个端一个端的扩展,也可以召唤其他端上的开发者来共同完成你在其他端上的组件(你总是可以在社区找到对某个功能有共同需求的开发者)。这里有一些在android端和ios端做扩展的文档可以参考。

    你应该将你的扩展发布到weex开发者可以方便找到和使用的渠道,比如npm. 推荐发布到npm,方便其他weex开发者使用。

    最重要的是,你的组件npm包的命名(注意不是组件的命名,是npm包的命名)需要遵守weex的命名规范:以weex-开头作为前缀,并且以-<platform>做为结尾后缀,除非你发布的包是三端的实现都包含在内的。这里以<weex-hello>这个组件的例子作为参考,这里注册了一个简单的自定义的组件。组件的名称为<hello>,开发者通过<hello>这个tag去使用这个组件,发到npm上的包名称是weex-hello-web.

    创建新组件

    组件和module是weex扩展的两大基础,组件是weex业务工程构建的基本单位。weex里已经内置了一些基础组件,包括最基础的三大组件<div>、<text>和<image>,以及其他一些扩展的组件,比如常用的<slider>、<scroller>、<list>、<input>、<video>等。内置组件的文档可以在官网文档区找到。

    如果你想创建一个新的组件(这里仅介绍web端创建组件的方法),你必须遵循以下步骤:

    在你的组件实现中必须继承Weex.Component 或者 Weex.Atomic这两个基类之一, 并选择性的重写其中的一些方法.你的组件的exports需要暴露一个init方法,并在其中使用Weex.registerComponent注册你的组件.

    这里用一个demo项目展示如何扩展一个新的组件

    看这个组件扩展的代码(web端上的组件):

    const attr = { // ... } const style = { // ... } const event = { // ... } // 每个扩展组件都需要实现一个init方法,Weex会通过这方法进行安装和注册. function init (Weex) { const Component = Weex.Component const extend = Weex.utils.extend // 组件的构造函数 function Hello (data) { Component.call(this, data) } // prototype继承 Hello.prototype = Object.create(Component.prototype) extend(Hello.prototype, proto) // 配置属性、样式以及事件 extend(Hello.prototype, { attr }) extend(Hello.prototype, { style: extend(Object.create(Component.prototype.style), style) }) extend(Hello.prototype, { event }) Weex.registerComponent('weex-hello', Hello) } // 暴露init方法接口. export default { init }

    上述代码摘引自weex-hello-web/src/index.js

    这个demo重写了基类Component中的create方法。你也可以选择重写Component中的一些其他方法来定制组件的行为。典型的方法包括:

    create: 创建组件的节点,在方法体中return这个节点. createChildren 创建子节点. insertBefore 在某个子节点之前插入一个新的子节点. appendChild 在子节点列表的最后加上一个节点. removeChild 移除一个子节点.

    更多关于组件定制和扩展的细节和代码展示,可以参考weex主仓库的代码,这里的组件基本上都是通过上述方式进行定义的。

    重要的一点,注册组件的关键方法是Weex.registerComponent,如示例里的weex-hello组件的注册:

    Weex.registerComponent('weex-hello', Hello)

    上述代码引自weex-hello-web/src/index.js

    在某个需要使用该组件的weex项目中使用Weex.install方法安装该组件:

    // import the original weex-html5. import weex from 'weex-html5' import hello from 'weex-hello-web' // install the component. weex.install(hello)

    上述代码引自weex_extend_demo/src/main.js

    在你的.we文件中直接使用这个组件:

    <template> <div> <weex-hello class="hello" style="txt-color:#fff;bg-color:green" value="WEEX" onclick="handleClick"> </weex-hello> </div> </template>

    上述代码引自weex_extend_demo/demo/index.we

    以上就是创建一个新组件以及在你的业务代码(DSL代码)中使用它的基本流程(__注__ : 我们习惯上把使用weex及weex规定的DSL语法开发的项目代码都叫DSL代码,把开发者称为DSL开发者,也就是编写.we文件的业务开发者,这不是某种规范,仅仅是一种习以为常的的叫法)。当然,这只是组件扩展的一个最基本的流程,然而在实现一个新组件的过程中,你可能会遇到以下几个疑问:

    在组件的constructor里需要干些什么?在组件的其他方法中分别需要做哪些事情?有哪些可以直接调用的父类的原型方法?组件从注册到渲染到页面上的执行流程是怎样的?

    这些问题将在下一篇《weex-html5组件进阶》中为你详细道来。

    扩展API

    weex里内置了一些API模块供DSL开发者们调用,如果你已经拥有weex开发经验你可能已经接触过了,比如stream模块,dom模块等等。目前在DSL代码里调用API模块的方式主要是:

    // 通过require方法引用模块,特别注意必须加上'@weex-module/'前缀 const stream = require('@weex-module/stream') // 调用stream模块的fetch方法 stream.fetch({ // ... })

    以stream模块为例,注意require引用的模块名称是模块里注册的名字,不是包名也不是文件名。你可以在官网文档里找到相关的API列表。weex使用require调用某个API模块的方式这里也有介绍:Module APIs

    你可以扩展自己的API模块,或者为某个已有的模块添加新的API. 比如,你可以添加一个API模块叫做user,在里面添加一些用户登录处理的API,比如login, logout等等。

    步骤:

    实现你的API module.在你的API安装模块里暴露一个init方法,并在这个方法里面使用Weex.registerAPIModules 注册你的API module.

    这里用一个例子展示如何扩展一个新的API模块

    创建一个文件user.js,在其中定义登录登出login/logout方法.

    const user = { // 定义用户登录方法. login (callbackId) { login.then(res => { this.sender.performCallback(callbackId, res) }).catch(err => { this.sender.performCallback(callbackId, err) }) }, // 定义用户登出方法. logout (callbackId) { logout.then(res => { this.sender.performCallback(callbackId, res) }).catch(err => { this.sender.performCallback(callbackId, err) }) } } // 定义user模块的元 (meta) 信息. const meta = { user: [{ name: 'login', args: ['function'] }, { name: 'logout', args: ['function'] }] } export default { init (Weex) { // 注册这个模块,最后一个参数是模块的元信息. Weex.registerApiModule('user', user, meta) } }

    这个简单的user helper模块就实现好了,我们可以给这个模块文件取个名字,比如说userHelper.js。

    在你的新的weex项目里安装这个模块:

    import Weex from 'weex-html5' import user from './apis/userHelper.js' Weex.install(user)

    安装了这个模块,你就可以在dsl代码里引用这个模块干点事情了:

    <template> <div> <div class="btn" onclick="handleClick"> <text>LOGIN</text> </div> </div> </template> <script> var userHelper = require('@weex-module/user') module.exports = { methods: { handleClick: function () { userHelper.login(function () { // ... do sth. in callback. }) } } } </script>

    定制加载器loader

    __Loader仅用于weex-html5 (web端),用来加载DSL打包出来的bundle代码__。native平台有其他加载bundle文件的机制。

    已有的加载器包括xhr, jsonp和source. 你可以使用weex.registerLoader注册一个新的加载器。例如,你有一个获取weex bundle的服务myServe.getWeexBundle, 通过这个服务可以加载weex bundle,为此你可以定义一个加载器:

    function loadByMyServe(pageId, callback) { myServe.getWeexBundle(pageId).then(function (bundle) { callback(bundle) }).catch(function(err) { callback(err) }) } // 暴露init方法用于Weex安装此加载器. export default { init (Weex) { Weex.registerLoader('myserve', loadByMyServe) } }

    在你的weex-html5项目的启动文件里安装并使用这个加载器:

    import Weex from 'weex-html5' // 或者import from './myserve.js',不管是import一个npm模块还是import一个文件. import loader from 'myLoader' Weex.install(loader) // 在init方法里使用这个加载器加载bundle文件. (function () { function getUrlParam (key) { const reg = new RegExp('[?|&]' + key + '=([^&]+)') const match = location.search.match(reg) return match && match[1] } const page = getUrlParam('page') || 'examples/build/index.js' Weex.init({ appId: location.href, loader: 'myserve', // 使用刚才定义的loader类型 source: page, rootId: 'weex' }) })();

    注意 : 一旦注册安装好自己的loader,你就可以把loader的注册名称做为参数传递在weex.init方法了,将init方法的参数配置loader指定为你的loader的注册名即可。

    以上是weex带来的扩展性里比较主要的一部分,更多实现细节可以在weex项目代码库以及weex的开源社区里找到。

    参考链接

    weex websiteweex docsweex 中文文档weex github 仓库
    最新回复(0)