教程(Tutorial)

CML 特点是“一端所见即多端所见”,你只需开发一次就能跑所有端。跟随这个教程,开启你的 chameleon 跨端开发。

视频教程

1 起步

1.1 安装运行环境

开发 chameleon 项目的第一步是要安装运行环境和全局安装 chameleon-tool。

[success] 运行环境 node >= 8.10.0npm >= 5.6.0

建议安装使用nvm管理 node 版本。

1.2 安装脚手架工具

  1. npm i -g chameleon-tool

注:暂不支持使用 yarn、cnpm 等第三方 npm 工具进行安装。

安装成功后,执行 cml -v 即可查看当前版本, cml -h查看命令行帮助文档,更多命令参见脚手架工具。接下来就可以使用它快速的创建 chameleon 项目。

1.3 创建与启动第一个 chameleon 项目

  • 执行 cml init project
  • 输入项目名称
  • 等待自动执行 npm install 依赖
  • 切换到项目根目录执行cml dev
  • 会自动打开预览界面 预览界面如下:
    教程  - 图1

web 端可以点击模拟器内页面右上角打开  新的浏览器窗口。

native 端的效果请  下载chameleon playground(目前可下载 Android 端,IOS 端即将发布)或者下载weex playground扫码预览

微信小程序端请下载微信开发者工具,打开项目根目录下的 /dist/wx 目录预览。支付宝小程序端请下载支付宝开发者工具,打开项目根目录下的 /dist/alipay 目录预览。百度小程序端请下载百度开发者工具,打开项目根目录下的 /dist/baidu 目录预览。

快应用正在测试中。

接下来,我们一起看看 chameleon 项目的目录结构与代码构成。

2 目录结构与  代码构成

2.1 目录结构

刚刚生成 chameleon 项目的目录结构如下:

  1. ├── chameleon.config.js // 项目的配置文件
  2. ├── dist // 打包产出目录
  3. ├── mock // 模拟数据目录
  4. ├── node_modules // npm包依赖,基于多态协议直接使用各端原生组件
  5. ├── package.json
  6. └── src // 项目源代码
  7. ├── app // app入口
  8. ├── components // 组件文件夹
  9. ├── pages // 页面文件夹
  10. ├── router.config.json // 路由配置文件
  11. └── store // 全局状态管理
 编辑器中语法高亮,暂时使用.vue的插件,参见编辑器插件,后续会推出更强大的插件。

chameleon 的目录结构将组件、页面、路由、 全局状态管理、静态资源、模拟数据等按照功能进行划分。更多参见目录结构。你可以留意到这个项目中的 app 入口、组件和页面  下都是.cml为后缀的文件,接下来我们就看看.cml文件代码构成。

2.2 .cml 文件代码构成

 从事过网页编程的人知道,网页编程采用的是 HTML + CSS + JS 这样的组合,同样道理,chameleon 中采用的是 CML + CMSS + JS。我们定义了扩展名为.cml的文件  将一个组件需要的所有部分组合(CML、CMSS、JS 逻辑交互、JSON 配置)在一起,更方便开发。

2.2.1 CML

CML(Chameleon Markup Language)用于描述页面的结构,我们知道 HTML 是有一套标准的语义化标签,例如  文本是<span>  按钮是<button>。CML 同样具有一套标准的标签,我们将标签定义为组件,CML 为用户提供了一系列组件。CML 中还支持模板语法,例如条件渲染、列表渲染,数据绑定等等,更多参见CML。简单举例:

  1. <template>
  2. <view>
  3. <!-- 数据绑定与计算属性 -->
  4. <text>{{ message }}</text>
  5. <text class="class1">{{ message2 }}</text>
  6. <!-- 条件与循环渲染 -->
  7. <view c-if="{{showlist}}">
  8. <view
  9. c-for="{{array}}"
  10. c-for-index="idx"
  11. c-for-item="itemName"
  12. c-key="city"
  13. >
  14. <text> {{idx}}: {{itemName.city}}</text>
  15. </view>
  16. </view>
  17. <!-- 事件绑定 -->
  18. <view c-bind:tap="changeShow"><text>切换展示</text></view>
  19. </view>
  20. </template>
  21. <script>
  22. class Index {
  23. data = {
  24. message: "Hello Chameleon!",
  25. array: [
  26. {
  27. city: "北京"
  28. },
  29. {
  30. city: "上海"
  31. },
  32. {
  33. city: "广州"
  34. }
  35. ],
  36. showlist: true
  37. };
  38. computed = {
  39. message2: function() {
  40. return "computed" + this.message;
  41. }
  42. };
  43. watch = {
  44. showlist(newVal, oldVal) {
  45. console.log(`showlist changed:` + newVal);
  46. }
  47. };
  48. methods = {
  49. changeShow() {
  50. this.showlist = !this.showlist;
  51. }
  52. };
  53. }
  54. export default new Index();
  55. </script>

同时,CML 支持使用类 VUE 语法,让你更快入手。

2.2.2 CMSS

CMSS(Chameleon Style Sheets)用于描述 CML 页面结构的样式语言,其具有大部分 CSS 的特性,也做了一些扩充和修改。

  • 1 支持 css 的预处语言less与 stylus
  • 2 新增了尺寸单位 cpx。在写 CSS 样式时,开发者需要考虑到手机设备的屏幕会有不同的宽度和设备像素比,采用一些技巧来换算一些像素单位。CMSS 在底层支持新的尺寸单位 cpx ,开发者可以免去换算的烦恼,只要交给 chameleon 底层来换算即可,由于换算采用的浮点数运算,所以运算结果会和预期结果有一点点偏差。
  • 3 为了各端样式一致性,内置了一些一致性基础样式
  • 4 chameleon 布局模型基于 CSS Flexbox,以便所有页面元素的排版能够一致可预测,同时页面布局能适应各种设备或者屏幕尺寸。
  • 5 cml 文件中支持样式多态,即可以针对不同的平台写不同的样式。
  • 6 如果只跨 web 和小程序端CMSS 将会更加灵活。简单举例:
  1. <style>
  2. @import "./global.css";
  3. @size: 10px;
  4. .header {
  5. width: @size;
  6. height: @size;
  7. }
  8. </style>

更多参见CMSS

2.2.3 JS 逻辑交互

JS 语法用于处理页面的逻辑部分,cml 文件<script></script>标签中的export default导出的 VM 对象即采用 JS 语法。它负责业务逻辑、交互逻辑的处理与  驱动视图更新,拥有完整的生命周期,watch,computed,数据双向绑定等优秀的特性,能够快速提高开发速度、降低维护成本。

  • data 为数据。
  • props 为  属性,父组件进行传递。
  • computed 为计算属性, 是动态的数据,可以对数据进行逻辑处理后返回结果。
  • watch 为侦听属性,监听数据的变化,触发相应操作。
  • methods 为方法 ,处理业务逻辑与交互逻辑。
  • beforeCreate、created 等生命周期,掌握生命周期的触发时机,做相应操作。简单举例:
  1. <script>
  2. class Index {
  3. // data
  4. data = {
  5. message: 'Hello',
  6. }
  7. // 计算属性
  8. computed = {
  9. reversedMessage: function () {
  10. return this.message.split('').reverse().join('')
  11. }
  12. }
  13. // 观察数据变化
  14. watch: {
  15. message: function (newV, oldV) {
  16. }
  17. }
  18. // 各种生命周期
  19. mounted: function(res) {
  20. // 模板或者html编译完成,且渲染到dom中完成,在整个vue的生命周期中只执行一次
  21. }
  22. }
  23. export default new Index();
  24. </script>

更多参见逻辑层

2.2.4 JSON 配置

JSON 配置部分用于描述  应用、页面或组件的配置信息,对应于小程序的 json 配置文件。可以在其中为各端做不同的配置。举例如下,base对象为各端共用的配置对象,都  引组件demo-comwx、alipay、baidu分别对应生成微信小程序、支付宝小程序和百度小程序的各自配置。更多参见组件配置

  1. <script cml-type="json">
  2. {
  3. "base": {
  4. "usingComponents": {
  5. "demo-com": "/components/demo-com/demo-com"
  6. }
  7. },
  8. "wx": {
  9. "navigationBarTitleText": "index",
  10. "backgroundTextStyle": "dark",
  11. "backgroundColor": "#E2E2E2"
  12. },
  13. "alipay": {
  14. "defaultTitle": "index",
  15. "pullRefresh": false,
  16. "allowsBounceVertical": "YES",
  17. "titleBarColor": "#ffffff"
  18. },
  19. "baidu": {
  20. "navigationBarBackgroundColor": "#ffffff",
  21. "navigationBarTextStyle": "white",
  22. "navigationBarTitleText": "index",
  23. "backgroundColor": "#ffffff",
  24. "backgroundTextStyle": "dark",
  25. "enablePullDownRefresh": false,
  26. "onReachBottomDistance": 50
  27. }
  28. }
  29. </script>

 通过以上对于 CML、CMSS、JS 交互逻辑以及 JSON 配置的学习,你已经具备了开发 chameleon 的页面和组件的能力, 可以参考卡片拖拽手势删除效果实现你想要的页面效果。但要想快速开发还需要掌握 chameleon 提供的组件和 API。

3 开发能力

3.1 组件

chameleon 提供了丰富的基础组件给开发者,开发者可以像搭积木一样,组合各种组件拼合成需要的功能。就像 HTML 的 div, p 等标签一样,在 chameleon 里边,你只需要在 WXML 写上对应的组件标签名字就可以把该组件显示在界面上,例如,你需要一个 switch 开关组件,你只需要这样写:

  1. <template>
  2. <switch
  3. checked="{{ switchValue }}"
  4. label="Switch"
  5. c-bind:change="switchChange"
  6. >
  7. </switch>
  8. </template>
  9. <script>
  10. class Switch {
  11. data = {
  12. switchValue: false
  13. };
  14. methods = {
  15. switchChange(e) {
  16. this.switchValue = e.detail.value;
  17. }
  18. };
  19. }
  20. export default new Switch();
  21. </script>
  22. <script cml-type="json">
  23. {
  24. "base": {}
  25. }
  26. </script>

使用组件的时候,还可以通过属性传递值给组件,让组件可以以不同的状态去展现,例如checked属性用于控制 switch 的  开关状态:组件的内部行为也会通过事件的形式让开发者可以感知,例如c-bind:change绑定 change 事件的处理函数为switchChange方法,在该方法中拿到改变的值,修改switchValue的值。更多的组件的使用参见组件

3.2 API

chameleon 封装了丰富的基础 api 库chameleon-api供开发者使用,这些 api 屏蔽了各平台的底层接口差异,例如数据存储功能,我们只需要这样使用,而不需要关心各端数据存储  接口的差异。

  1. import cml from "chameleon-api";
  2. cml.setStorage("name", "chameleon").then(() => {}, function(err) {});

例如弹出 toast 方法,只需要这样使用:

  1. import cml from "chameleon-api";
  2. cml.showToast({
  3. message: "Hello chameleon!",
  4. duration: 1000
  5. });

注意:接口均以 promise 形式进行返回,所以你可以结合异步流程控制如 async、await 进行操作。更多 API 能力参见API

3.3 路由管理

chameleon 项目是应用级的项目,应用内允许多个页面的存在,下面学习项目中多个页面之间的路由管理与跨应用之间的跳转。chameleon 项目内置了一套各端统一的路由管理方式,项目根目录  下的src/router.config.json是路由的配置文件,内容如下:

  1. {
  2. "mode": "history",
  3. "domain": "https://www.chameleon.com",
  4. "routes":[
  5. {
  6. "url": "/cml/h5/index",
  7. "path": "/pages/index/index",
  8. "mock": "index.php"
  9. }
  10. ]
  11. }
  • mode 为 web 端路由模式,分为hashhistory
  • domain 为 web 端地址的域名。
  • routes 为路由配置
    • path 为路由对应的 cml 文件的路径,以 src 目录下开始的绝对路径,以/开头。
    • url 为 web 端的访问路径
    • mock 为该路由对应的mock 文件(仅模拟模板下发需要)
  • 小程序端,构建时会将router.config.json的内容,插入到 app.json 的 pages 字段,实现小程序端的路由。
    路由跳转分为应用内跳转应用间跳转chameleon-api都提供了相应的方法:

  • navigateTo 打开新页面

  • redirectTo 页面  重定向
  • navigateBack 页面返回
  • open 打开其他应用页面
    例如应用内打开新页面:
  1. import cml from 'chameleon-api';
  2. cml.navigateTo({
  3. path: '/pages/page2/page2'
  4. })

更多参见路由配置

3.4 数据管理

当项目中的组件和页面越来越多,越来越复杂  后,他们之间会出现  共同管理数据状态的情况,这时我们建议使用 chameleon 提供的全局数据管理chameleon-store进行管理,它位于项目根目录下的src/store中 ,目录结构如下:

  1. └── store
  2. ├── action-types.js # 定义 actions 的类型
  3. ├── actions.js # 根级别的 actions
  4. ├── getter-types.js # 定义 getters 的类型
  5. ├── getters.js # 根级别的 getters
  6. ├── index.js # 我们组装模块并导出 store 的地方
  7. ├── mutation-types.js # 定义 mutations 的类型
  8. ├── mutations.js # 根级别的 mutation
  9. ├── state.js # 组件初始状态数据
  10. └── modules # 子模块
  11. ├── ...

类似 Vuex 数据理念和语法规范,chameleon-store 主要有以下核心概念:

可以通过cml init project —demo todo  初始化todo 示例 demo,学习其中对于  数据管理的使用。

3.5 自由定制 API 和组件

目前学习到现在, 我们都是利用一套代码实现多端的开发,但是当你遇到特殊的情况时,一套代码无法满足多端的需求时,chameleon 提供的多态协议,可以让你自由的扩展 API 和组件。有如下几种  情况:

  • 第一 定制化的组件,比如要使用 echarts 组件,这时就需要使用多态组件实现,例如手把手教你系列- 实现多态 echart
  • 第二 定制化的底层接口,可以参考手把手教你系列- 实现多态 API
  • 第三 业务需求导致的各端差异化实现,比如 web 端和小程序要有不用的逻辑处理,可以利用多态组件多态接口实现。
    注:多态协议是 Chameleon 业务层代码和各端底层组件和接口的分界点,是跨端底层差异化的解决方案,普通用户开发基本上使用不到多态协议,因为 chameleon 已经  使用多态协议封装了丰富的组件和接口。

4 工程化能力

当我们执行cml dev进行开发时,就已经使用了 chameleon 的工程化能力,如果还想使用热更新与自动刷新、调试窗口、mock 数据、代码的压缩、资源发布路径、打包资源分析、文件指纹等功能就需要进一步的学习。

mock 数据是本地开发必不可少的工作,chameleon 项目中在mock文件夹的文件中写 express 中间件的形式 mock 数据,更多参见 数据 mock,例如:

  1. module.exports = [
  2. {
  3. method: ["get", "post"],
  4. path: "/api/getMessage",
  5. controller: function(req, res, next) {
  6. res.json({
  7. total: 0,
  8. message: [
  9. {
  10. name: "Hello chameleon!"
  11. }
  12. ]
  13. });
  14. }
  15. }
  16. ];

chameleon 的其他工程化配置统一收敛在项目根目录  下的chameleon.config.js文件,在该文件中可以使用全局对象 cml 的 api 去操作配置对象。例如:

配置当前项目支持的端

  1. cml.config.merge({
  2. platforms: ["web", "wx"]
  3. });

配置是否进行文件压缩

  1. cml.config.merge({
  2. web: {
  3. dev: {
  4. minimize: true
  5. }
  6. }
  7. });

配置资源发布路径,分离线上和线下的资源路径。

  1. cml.config.merge({
  2. web: {
  3. build: {
  4. publicPath: "http://www.chameleon.com/static"
  5. }
  6. }
  7. });

更多配置参见工程配置

5 渐进式跨端

如果你既想一套代码运行多端,又不用大刀阔斧的重构项目,可以将多端重用组件用 Chameleon 开发,直接在原有项目里面调用。参见导入与导出。也有如下手把手实例进行参考

6 端渲染能力接入

如果你需要跨 native 端渲染,则需要接入chameleon SDK,目前支持的渲染引擎是 weex,即将支持 react native,使用时二者选其一作为项目的 native 渲染引擎。chameleon SDK 包括对原生组件和本地 api 能力的扩展,对性能和稳定性的优化。使用方式可以参见Android Chameleon SDKIOS Chameleon SDK

7 智能规范校验

chameleon 提供了多种规范校验,对这些规范的学习可以提高开发效率,保证代码质量。接口校验语法 是使用多态协议扩展多态组件和多态接口时使用。可以通过配置进行开启或者关闭。全局变量校验 是保证跨端代码全局变量正确性的检查方法,可以通过配置进行开启或者关闭。代码规范校验 是对项目结构,文件规范,样式规范等进行校验,可以通过配置进行开启或者关闭。

更多示例