cml
(Chameleon 变色龙) 作为真正让一套代码运行多端的框架,提供标准的MVVM模式,统一开发各类终端。
同时,拥有各端独立的 运行时框架(runtime)
、数据管理(store)
、组件库(ui)
、接口(api)
。
此外,cml
在跨端能力加强
、能力统一
、表现一致
等方面做了许多工作。
今天,为了让大家的项目优雅升级,快速接入,给你带来一份丰盛的cml迁移指南~
送上5分钟视频教程
源码地址:
目录结构
和微信小程序一样,cml
包含一个描述整体程序的 app
和多个描述各自页面的 page
。
小程序目录结构
.├── components // 包含各个组件├── pages // 包含各个页面├── app.js // 包含各个组件├── app.js // 应用启动入口├── app.json // 全局配置├── app.wxss // 全局样式└── project.config.json // 项目配置文件复制代码
cml目录结构
.├── dist // 各个端构建结果│ ├── alipay │ ├── baidu │ ├── wx │ ├── web │ ├── weex │ └── config.json // 跨端配置map映射表├── node_modules // 第三方库├── mock // 模拟 接口数据 和 模板数据├── src // 源代码开发目录│ ├── app // 应用启动入口│ ├── assets // 静态资源│ ├── components // 包含组件│ ├── pages // 包含页面│ ├── store //数据管理│ └── router.config.json // 路由配置文件├── chameleon.config.js // 项目配置文件└── package.json // npm包配置文件复制代码
如何修改配置
在小程序项目里面,分为:
可以在项目根目录使用 project.config.json
文件对项目进行配置。
配置示例:
{ "miniprogramRoot": "./src", "debugOptions": {}}复制代码
小程序根目录下的 app.json
文件用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等
配置示例:
{ "pages": ["pages/index/index", "pages/logs/index"], "window": { "navigationBarTitleText": "Demo" }, "networkTimeout": { "request": 10000, "downloadFile": 10000 }}复制代码
每一个小程序页面也可以使用 .json
文件来对本页面的窗口表现进行配置。
页面的配置只能设置 app.json
中部分 window
配置项的内容,页面中配置项会覆盖 app.json
的 window
中相同的配置项。
配置示例:
{ "navigationBarBackgroundColor": "#ffffff", "navigationBarTextStyle": "black", "navigationBarTitleText": "微信接口功能演示", "backgroundColor": "#eeeeee", "backgroundTextStyle": "light"}复制代码
同样,在 cml
项目里面,分为:
chameleon.config.js
为项目的配置文件,你可以定制化构建,比如是否带hash,是否压缩等等。
配置示例:
// 设置静态资源的线上路径const publicPath = '//www.static.chameleon.com/static';// 设置api请求前缀const apiPrefix = 'https://api.chameleon.com';// 合并配置cml.config.merge({ wx: { build: {apiPrefix} }, alipay: { build: {apiPrefix} }, baidu: { build: {apiPrefix} }, web: { dev: { hot: true, console: true }, build: { publicPath: `${publicPath}/web`, apiPrefix } }, weex: { build: { publicPath: `${publicPath}/weex`, apiPrefix } }})复制代码
cml —— 全局配置
cml
项目 app
目录下的 app.cml
文件的 <script cml-type="json" />
用来对 cml
应用 进行全局配置,具有 跨端配置 和 差异化 的能力
配置示例:
复制代码
通过 usingComponents
配置 组件路径
注册引用的组件。
配置示例:
复制代码
如何使用路由能力
小程序配置路由
配置项列表的 pages
字段用于指定小程序由哪些页面组成,每一项都对应一个页面的 路径+文件名
信息。
数组的第一项代表小程序的初始页面(首页)。新增/减少页面,需要对 pages
数组进行修改。
如果项目有 pages/index/index.wxml
、pages/logs/logs.wxml
两个页面,则需要在 app.json
中写
{ "pages": ["pages/index/index", "pages/logs/logs"]}复制代码
cml配置路由
是路由的配置文件,cml
内置了一套各端统一的路由管理方式。相应有 cml
路由配置映射如下:
{ "mode": "history", "domain": "https://www.chameleon.com", "routes":[ { "url": "/cml/h5/index", "path": "/pages/index/index", "mock": "index.php" }, { "url": "/cml/h5/logs", "path": "pages/logs/logs", "mock": "logs.php" } ]}复制代码
文件名不需要写文件后缀,cml
框架会自动去寻找对于位置的 .cml
文件进行处理。
小程序使用路由
- 打开新页面:调用 API
- 页面重定向:调用 API
- 页面返回:调用 API
- 打开另一个小程序:调用 API
- 返回到上一个小程序:调用 API
cml使用路由
依据统一资源索引URI,自适应打开不同环境同一路由PATH:
- 打开新页面:调用 chameleon-api
- 页面重定向:调用 chameleon-api
- 页面返回:调用 chameleon-api
- 打开另一个跨端应用:调用 chameleon-api
- 返回到上一个跨端应用:调用 chameleon-api
如何注册
如何注册程序
小程序注册程序
在小程序项目里面,App()
函数用来注册一个小程序。接受一个 Object
参数,其指定小程序的生命周期回调等。
示例代码
App({ onLaunch(options) { // Do something initial when launch. }, globalData: 'I am global data'})复制代码
cml注册程序
示例代码
复制代码
细心的你会发现,
小程序中app.json app.js app.wxss
和 src/app/app.cml
的对应关系如下
小程序 app.js | cml项目 src/app/app.cml |
---|---|
app.js | <script></script> |
app.wxss | <style></style> |
app.json | <script cml-type="json"></script> |
如何注册页面
小程序注册页面
在小程序项目里面,Page(Object)
函数用来注册一个页面。接受一个 Object
类型参数,其指定页面的初始数据、生命周期回调、事件处理函数等。
示例代码:
// index.jsPage({ data: { text: 'This is page data.' }, changeText: function(e) { // sent data change to view this.setData({ text: 'CML' }) }})复制代码
cml注册页面
示例代码
复制代码
如何注册组件
小程序注册组件
在小程序项目里面, Component(Object)
构造器可用于定义组件,调用 Component
构造器时可以指定组件的属性、数据、方法等。
示例代码
Component({ properties: { myProperty: { // 属性名 type: String, // 类型(必填) value: '' // 属性初始值(可选) }, myProperty2: String // 简化的定义方式 }, data: { text: '' }, // 私有数据,可用于模板渲染 // 生命周期函数,可以为函数,或一个在methods段中定义的方法名 attached() { }, ready() { }, methods: { onMyButtonTap() { this.setData({ // 更新属性和数据的方法与更新页面数据的方法类似 text: 'wx' }) } }})复制代码
cml注册组件
示例代码
复制代码
如何声明生命周期
统一各端应用生命周期的定义,是跨端框架的重要组成,也是迁移的必经之路。
小程序声明生命周期
可以在 App(Object)
、Page(Object)
、Component(Object)
传入Object
参数,其指定小程序的生命周期回调等
代码示例
// index.jsPage({ onLoad(options) { // Do some initialize when page load. }, onReady() { // Do something when page ready. }, onShow() { // Do something when page show. }, onHide() { // Do something when page hide. }, onUnload() { // Do something when page close. }, onShareAppMessage() { // return custom share data when user share. }})复制代码
cml声明生命周期
在.cml
文件 <script />
代码块返回的对象实例,其指定生命周期回调
示例代码
复制代码
App 生命周期 映射
小程序 app.js
中的生命周期 -> cml src/app/app.cml
小程序 | chameleon |
---|---|
onLaunch | beforeCreate |
onShow | mounted |
onHide | destroyed |
Page 生命周期 映射
小程序 Page()
中的生命周期 -> cml src/pages/mypage/mypage.cml
小程序 | chameleon |
---|---|
onLoad | beforeCreate |
onShow | mounted |
onUnload | destroyed |
onReady | |
onHide | |
onShareAppMessage |
Component 生命周期 映射
小程序 Component()
中的生命周期 -> cml src/components/mycomponent/mycomponent.cml
小程序 | chameleon |
---|---|
created | created |
attached | beforeMount |
ready | mounted |
detached | destroyed |
生命周期总结
每个 cml
实例(App
、Page
、Component
)在被创建时都要经过一系列的初始化过程 ————
例如,需要设置数据监听、编译模板、将实例挂载到 CML节点
并在数据变化时更新 CML节点
等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给开发者在不同阶段添加自己的代码的机会。
cml
为App
、页面Page
、组件Component
提供了一系列生命周期事件,保障应用有序执行。
另外,如果你想使用某个端特定的生命周期,你可以从业务出发使用 。
数据如何响应到视图
如今,双向数据绑定&单向数据流 已深入开发者日常,MVMM开发模式算是框架标配。
、、 是如何书写的呢?
示例代码
小程序使用数据响应
复制代码 { {message}} WEBVIEW APP MINA { {item}}
// page.jsPage({ data: { message: 'Hello MINA!', view: 'MINA', array: [1, 2, 3, 4, 5] }, onLoad() { this.setData({ message: 'wx' }) }})复制代码
cml使用数据响应
复制代码 { {message}} WEBVIEW APP MINA { {item}}
数据响应总结
cml
运行时框架 提供了跨端响应式数据绑定系统(Data binding),当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。
只需要将 view<-->model
交互部分逻辑,作简单迁移,便可使它成为跨多端的数据响应系统。
事件交互
cml
支持一些基础的,保障各端效果(类型
、绑定
、事件对象
)一致运行。
示例代码
小程序使用事件
Click me! 复制代码
// page.jsPage({ tapName(event) { console.log(event) }})复制代码
cml使用事件
复制代码 Click me!
事件使用总结
同时,还支持,用于父子组件之间的通信。
另外,如果你想要使用某个端特定的事件,cml
并不会限制你的自由发挥,你可以从业务出发使用 或者 差异化实现功能。
布局和外观
各端描述 布局和外观
的实现存在差异,包括不限于 布局
、盒模型
、定位
、文本
。
所以, cml
框架内置能力。
并且,定义了用于描述页面的样式规范。
如何导入外部样式
使用 @import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用 ;
表示语句结束。
小程序导入外部样式
示例代码:
/** common.wxss **/.small-p { padding:5px;}复制代码
/** app.wxss **/@import "common.wxss";.middle-p { padding:15px;}复制代码
cml导入外部样式
示例代码:
/** common.css **/.small-p { padding: 5px;}复制代码
复制代码
样式使用总结
同时,为了统一多端尺寸单位,呈现效果一致,同时页面响应式布局,cml
项目统一采用 作为尺寸单位,规定以屏幕750px(占满屏幕)视觉稿作为标准。
而且,各端样式表拥有的能力 ,是项目迁移的主要阵地之一。
另外,如果你想要使用某个端特定的样式能力,cml
并不会限制你的自由发挥,你可以从业务出发使用
注意:由于chameleon应用是 跨多端web native 小程序
框架,如果需要跨native
,必须使用 进行样式布局!!!
组件
cml
项目一切皆组件。组件(Component)是视图的基本组成单元。
框架为开发者提供了一系列,开发者可以通过组合这些进行快速开发。
如:
复制代码 view 基础组件 text 基础组件
同时,cml
支持简洁的组件化编程。
自定义组件
开发者可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用。自定义组件在使用时与基础组件非常相似。
如何创建自定义组件
小程序创建自定义组件
代码示例:
Component({ properties: { // 这里定义了innerText属性,属性值可以在组件使用时指定 innerText: { type: String, value: 'default value', } }, data: { // 这里是一些组件内部数据 someData: {} }, methods: { // 这里是一个自定义方法 customMethod() {} }})复制代码
cml创建自定义组件
示例代码
复制代码
如何使用自定义组件
使用已注册的自定义组件前,首先要进行引用声明。此时需要提供每个自定义组件的标签名和对应的自定义组件文件路径。
小程序使用自定义组件
代码示例:
在 page.json
中进行引用声明
{ "usingComponents": { "component-tag-name": "path/to/the/custom/component" }}复制代码
在 page.wxml
中使用
复制代码
cml使用自定义组件
代码示例:
在 page.cml
中<script cml-type='json' />
进行引用声明
复制代码
在 page.cml
中<template />
使用
复制代码
如何实现父子组件事件通信
事件系统是组件间通信的主要方式之一。自定义组件可以触发任意的,引用组件的页面可以监听这些事件。
小程序组件通信
代码示例:
复制代码
// 页面 page.jsPage({ methods: { onMyEvent(e) { console.log(e.detail) // 自定义组件触发事件时提供的detail对象 } }})复制代码
复制代码
// 组件 my-component.jsComponent({ methods: { onTap() { this.triggerEvent('customevent', {}) // 触发 自定义组件事件 } }})复制代码
cml组件通信
代码示例:
复制代码
复制代码
组件使用总结
和小程序一样,cml框架
提供了大量和,抹平多端差异,便于开发者通过组合这些组件,创建出强大的应用程序。
扩展组件需要额外引入。如:
复制代码
在执行 cml build
构建打包时,cml 框架
会按需打包引用的内置组件和扩展组件,为代码瘦身。
和 都是支持跨多端的,对于一些没有提供的某个端的组件,可以通过来实现。
如果希望使用小程序端的原生组件,那么可以在原生标签前加上 origin-*
,cml
框架会渲染原生组件
注意:origin-*
只能在中使用!!
如在 map.wx.cml
文件中使用原生地图组件 <map/>
:
复制代码
如何调用平台接口能力
在小程序里面,可以通过微信原生 API
,调起如获取用户信息,本地存储,支付功能等。
示例代码
try { wx.setStorageSync('name', 'Hanks')} catch (e) { console.error(e)}复制代码
同样,在 cml 项目里面可以这样调用:
示例代码
import cml from 'chameleon-api'cml.setStorage('name', 'Hanks').then((res)=>{ console.log(res)},function(e){ console.error(e)})复制代码
接口使用总结
cml
框架提供了丰富的多态接口,可以调起各端提供的原生能力,如系统信息、元素节点信息、动画效果、本地存储、网络请求、地理位置等。请参考 文档。
chameleon-api
提供的接口都是支持跨多端的,对于一些没有提供的某个端的原生接口,可以通过来调用。
迁移实例
下面给出各端(vue、weex、小程序)迁移cml指南
以及 cml 导出组件到各端指南
的具体迁移文档: