加载中...

1.4.8 扩展Web


扩展 weex-html5

  1. <span class="weex-version">0.4</span>

简介

Weex是一个高可扩展性的跨平台动态化开发方案,你可以在现有组件基础上定制自己需要的三端组件。你可以为Weex API模块添加新的方法,或者创建新的API模块和新的加载器。按照以下几个步骤扩展你的组件,API或者加载器。

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

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

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

最重要的是,你的组件的命名需要遵守weex组件命名规范:以weex-开头作为组件的前缀,并且以-<platform>做为结尾后缀,除非你发布的包是三端的实现都包含在内的。这里有个<weex-hello-web>的例子作为参考,这里注册了一个简单的自定义的组件。

创建新组件

步骤:

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

这里用一个例子展示如何扩展一个新的组件

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

  1. const attr = {
  2. // ...
  3. }
  4. const style = {
  5. // ...
  6. }
  7. const event = {
  8. // ...
  9. }
  10. // 每个扩展组件都需要实现一个init方法,Weex会通过这方法进行安装和注册.
  11. function init (Weex) {
  12. const Component = Weex.Component
  13. const extend = Weex.utils.extend
  14.  
  15. // 组件的构造函数
  16. function Hello (data) {
  17. Component.call(this, data)
  18. }
  19.  
  20. // prototype继承
  21. Hello.prototype = Object.create(Component.prototype)
  22. extend(Hello.prototype, proto)
  23.  
  24. // 配置属性、样式以及事件
  25. extend(Hello.prototype, { attr })
  26. extend(Hello.prototype, {
  27. style: extend(Object.create(Component.prototype.style), style)
  28. })
  29. extend(Hello.prototype, { event })
  30.  
  31. Weex.registerComponent('weex-hello', Hello)
  32. }
  33.  
  34. // 暴露init方法接口.
  35. export default { init }

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

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

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

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

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

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

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

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

  1. // import the original weex-html5.
  2. import weex from 'weex-html5'
  3. import hello from 'weex-hello-web'
  4. // install the component.
  5. weex.install(hello)

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

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

  1. <template>
  2. <div>
  3. <weex-hello class="hello" style="txt-color:#fff;bg-color:green" value="WEEX" onclick="handleClick">
  4. </weex-hello>
  5. </div>
  6. </template>

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

扩展API

你可以扩展新的API模块,或者为某个已有的模块添加新的API. 比如,你可以添加一个API模块叫做user,在里面添加一些用户登录登出处理的API,比如login, logout等等。你可以通过require('@weex-module/moduleName)[methodName](arg1, arg2, ...) (Module APIs)的方式调用你的API.

步骤:

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

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

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

  1. const user = {
  2. // 定义用户登录方法.
  3. login (callbackId) {
  4. login.then(res => {
  5. this.sender.performCallback(callbackId, res)
  6. }).catch(err => {
  7. this.sender.performCallback(callbackId, err)
  8. })
  9. },
  10.  
  11. // 定义用户登出方法.
  12. logout (callbackId) {
  13. logout.then(res => {
  14. this.sender.performCallback(callbackId, res)
  15. }).catch(err => {
  16. this.sender.performCallback(callbackId, err)
  17. })
  18. }
  19. }
  20.  
  21. // 定义user模块的元 (meta) 信息.
  22. const meta = {
  23. user: [{
  24. name: 'login',
  25. args: ['function']
  26. }, {
  27. name: 'logout',
  28. args: ['function']
  29. }]
  30. }
  31.  
  32. export default {
  33. init (Weex) {
  34. // 注册这个模块,最后一个参数是模块的元信息.
  35. Weex.registerApiModule('user', user, meta)
  36. }
  37. }

这个简单的user helper模块就实现好了,可以发布到npm上,我们可以给这个模块取个名字,比如说weex-user-helper

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


  1. import Weex from 'weex-html5'
  2. import user from 'weex-user-helper'
  3.  
  4. Weex.install(user)

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

  1. <template>
  2. <div>
  3. <div class="btn" onclick="handleClick">
  4. <text>LOGIN</text>
  5. </div>
  6. </div>
  7. </template>
  8.  
  9. <script>
  10. var userHelper = require('@weex-module/user')
  11. module.exports = {
  12. methods: {
  13. handleClick: function () {
  14. userHelper.login(function () {
  15. // ... do sth. in callback.
  16. })
  17. }
  18. }
  19. }
  20. </script>

定制加载器loader

Loader仅用于weex-html5 (web端)加载dsl打包出来的bundle代码,native平台有其他的加载机制

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

  1. function loadByMyServe(pageId, callback) {
  2. myServe.getWeexBundle(pageId).then(function (bundle) {
  3. callback(bundle)
  4. }).catch(function(err) {
  5. callback(err)
  6. })
  7. }
  8.  
  9. // 暴露init方法用于Weex安装此加载器.
  10. export default {
  11. init (Weex) {
  12. Weex.registerLoader('myserve', loadByMyServe)
  13. }
  14. }

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

  1. import Weex from 'weex-html5'
  2.  
  3. // 或者import from './myserve.js',不管是import一个npm模块还是import一个文件.
  4. import loader from 'myLoader'
  5.  
  6. Weex.install(loader)
  7.  
  8. // 在init方法里使用这个加载器加载bundle文件.
  9. (function () {
  10. function getUrlParam (key) {
  11. const reg = new RegExp('[?|&]' + key + '=([^&]+)')
  12. const match = location.search.match(reg)
  13. return match && match[1]
  14. }
  15. const page = getUrlParam('page') || 'examples/build/index.js'
  16. Weex.init({
  17. appId: location.href,
  18. loader: 'myserve', // 使用刚才定义的loader类型
  19. source: page,
  20. rootId: 'weex'
  21. })
  22. })();

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


还没有评论.