教程
CML特点是“一端所见即多端所见”你只需开发一次就能跑所有端。
跟随这个教程开启你的chameleon跨端开发。
1 起步
1.1 安装运行环境
开发chameleon项目的第一步是要安装运行环境和全局安装chameleon-tool。
**[success] 运行环境 **
node >= 8.10.0
npm >= 5.6.0
建议安装使用nvm管理node版本。
1.2 安装脚手架工具
npm i -g chameleon-tool
安装成功后执行 cml -v
即可查看当前版本 cml -h
查看命令行帮助文档更多命令参见脚手架工具。接下来就可以使用它快速的创建chameleon项目。
**[success] 尝鲜版 **
尝鲜版提供了百度小程序和支付宝小程序的支持
如果想提前使用可移步这里查看使用
1.3 创建与启动第一个chameleon项目
- 执行
cml init project
- 输入项目名称
- 等待自动执行npm install依赖
- 切换到项目根目录执行
cml dev
- 会自动打开预览界面 预览界面如下
web端可以点击模拟器内页面右上角打开新的浏览器窗口。
native端的效果请下载chameleon playground(目前可下载Android端IOS端即将发布)或者下载weex playground扫码预览
小程序端请下载微信开发者工具打开项目根目录下的 /dist/wx
目录预览。
支付宝、百度小程序正在alpha版本中这里查看使用。快应用正在测试中。
接下来我们一起看看chameleon项目的目录结构与代码构成。
2 目录结构与代码构成
2.1 目录结构
刚刚生成chameleon项目的目录结构如下
├── chameleon.config.js // 项目的配置文件
├── dist // 打包产出目录
├── mock // 模拟数据目录
├── node_modules // npm包依赖基于多态协议直接使用各端原生组件
├── package.json
└── src // 项目源代码
├── app // app入口
├── components // 组件文件夹
├── pages // 页面文件夹
├── router.config.json // 路由配置文件
└── 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
CMLChameleon Markup Language用于描述页面的结构我们知道HTML是有一套标准的语义化标签例如文本是<span>
按钮是<button>
。CML同样具有一套标准的标签我们将标签定义为组件
CML为用户提供了一系列组件。CML中还支持模板语法例如条件渲染、列表渲染数据绑定等等更多参见CML。简单举例
<template>
<view>
<!-- 数据绑定与计算属性 -->
<text>{{ message }}</text>
<text class="class1">{{ message2 }}</text>
<!-- 条件与循环渲染 -->
<view c-if="{{showlist}}">
<view c-for="{{array}}" c-for-index="idx" c-for-item="itemName" c-key="city" >
<text> {{idx}}: {{itemName.city}}</text>
</view>
</view>
<!-- 事件绑定 -->
<view c-bind:tap="changeShow"><text>切换展示</text></view>
</view>
</template>
<script>
class Index {
data = {
message: 'Hello Chameleon!',
array: [{
city: '北京'
},
{
city: '上海'
},
{
city: '广州'
}],
showlist: true
}
computed = {
message2: function() {
return 'computed' + this.message;
}
}
watch = {
showlist(newVal, oldVal) {
console.log(`showlist changed:`+ newVal)
}
}
methods = {
changeShow() {
this.showlist = !this.showlist;
}
}
}
export default new Index();
</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将会更加灵活。
简单举例
<style>
@import './global.css';
@size: 10px;
.header {
width: @size;
height: @size;
}
</style>
更多参见CMSS。
2.2.3 JS逻辑交互
JS语法用于处理页面的逻辑部分cml文件<script></script>
标签中的export default
导出的VM对象即采用JS语法。它负责业务逻辑、交互逻辑的处理与驱动视图更新拥有完整的生命周期watchcomputed数据双向绑定等优秀的特性能够快速提高开发速度、降低维护成本。
- data为数据。
- props为属性父组件进行传递。
- computed为计算属性是动态的数据可以对数据进行逻辑处理后返回结果。
- watch为侦听属性监听数据的变化触发相应操作。
- methods为方法处理业务逻辑与交互逻辑。
- beforeCreate、created等生命周期掌握生命周期的触发时机做相应操作。
简单举例
<script>
class Index {
// data
data = {
message: 'Hello',
}
// 计算属性
computed = {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
// 观察数据变化
watch: {
message: function (newV, oldV) {
}
}
// 各种生命周期
mounted: function(res) {
// 模板或者html编译完成,且渲染到dom中完成,在整个vue的生命周期中只执行一次
}
}
export default new Index();
</script>
更多参见逻辑层。
2.2.4 JSON配置
JSON配置部分用于描述应用、页面或组件的配置信息对应于小程序的json配置文件。可以在其中为各端做不同的配置。举例如下base
对象为各端共用的配置对象,都引组件demo-com
。wx、alipay、baidu
分别对应生成微信小程序、支付宝小程序和百度小程序的各自配置。更多参见组件配置。
<script cml-type="json">
{
"base": {
"usingComponents": {
"demo-com": "/components/demo-com/demo-com"
}
},
"wx": {
"navigationBarTitleText": "index",
"backgroundTextStyle": "dark",
"backgroundColor": "#E2E2E2"
},
"alipay": {
"defaultTitle": "index",
"pullRefresh": false,
"allowsBounceVertical": "YES",
"titleBarColor": "#ffffff"
},
"baidu": {
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "index",
"backgroundColor": "#ffffff",
"backgroundTextStyle": "dark",
"enablePullDownRefresh": false,
"onReachBottomDistance": 50
}
}
</script>
通过以上对于CML、CMSS、JS交互逻辑以及JSON配置的学习你已经具备了开发chameleon的页面和组件的能力, 可以参考卡片拖拽手势删除效果实现你想要的页面效果。但要想快速开发还需要掌握chameleon提供的组件和API。
3 开发能力
3.1 组件
chameleon提供了丰富的基础组件给开发者开发者可以像搭积木一样组合各种组件拼合成需要的功能。
就像 HTML 的 div, p 等标签一样在chameleon里边你只需要在 WXML 写上对应的组件标签名字就可以把该组件显示在界面上例如你需要一个switch开关组件你只需要这样写
<template>
<switch
checked="{{ switchValue }}"
label="Switch"
c-bind:change="switchChange"
>
</switch>
</template>
<script>
class Switch {
data = {
switchValue: false
}
methods = {
switchChange (e) {
this.switchValue = e.detail.value
}
}
};
export default new Switch();
</script>
<script cml-type="json">
{
"base": {}
}
</script>
使用组件的时候还可以通过属性传递值给组件让组件可以以不同的状态去展现例如checked
属性用于控制switch的开关状态:
组件的内部行为也会通过事件的形式让开发者可以感知例如c-bind:change
绑定change事件的处理函数为switchChange
方法在该方法中拿到改变的值修改switchValue
的值。
更多的组件的使用参见组件。
3.2 API
chameleon封装了丰富的基础api库chameleon-api
供开发者使用这些api屏蔽了各平台的底层接口差异例如数据存储功能我们只需要这样使用而不需要关心各端数据存储接口的差异。
import cml from 'chameleon-api'
cml.setStorage('name', 'chameleon').then(()=>{
},function(err){
})
例如弹出toast方法只需要这样使用
import cml from 'chameleon-api'
cml.showToast({
message: 'Hello chameleon!',
duration: 1000
})
注意接口均以promise形式进行返回所以你可以结合异步流程控制如async、await进行操作。
更多API能力参见API
3.3 路由管理
chameleon项目是应用级的项目应用内允许多个页面的存在下面学习项目中多个页面之间的路由管理与跨应用之间的跳转。
chameleon项目内置了一套各端统一的路由管理方式项目根目录下的src/router.config.json
是路由的配置文件,内容如下:
{
"mode": "history",
"domain": "https://www.chameleon.com",
"routes":[
{
"url": "/cml/h5/index",
"path": "/pages/index/index",
"mock": "index.php"
}
]
}
- mode 为web端路由模式分为
hash
或history
。 - domain 为web端地址的域名。
- routes 为路由配置
- path为路由对应的cml文件的路径,以src目录下开始的绝对路径以/开头。
- url为web端的访问路径
- mock为该路由对应的mock文件(仅模拟模板下发需要)
- 小程序端构建时会将
router.config.json
的内容插入到app.json的pages字段实现小程序端的路由。
- navigateTo 打开新页面
- redirectTo 页面重定向
- navigateBack 页面返回
- open 打开其他应用页面
例如应用内打开新页面
import cml from 'chameleon-api';
cml.navigateTo({
path: '/pages/page2/page2'
})
更多参见路由配置。
3.4 数据管理
当项目中的组件和页面越来越多越来越复杂后他们之间会出现共同管理数据状态的情况这时我们建议使用chameleon提供的全局数据管理chameleon-store
进行管理它位于项目根目录下的src/store
中目录结构如下
└── store
├── action-types.js # 定义 actions 的类型
├── actions.js # 根级别的 actions
├── getter-types.js # 定义 getters 的类型
├── getters.js # 根级别的 getters
├── index.js # 我们组装模块并导出 store 的地方
├── mutation-types.js # 定义 mutations 的类型
├── mutations.js # 根级别的 mutation
├── state.js # 组件初始状态数据
└── modules # 子模块
├── ...
类似 Vuex 数据理念和语法规范chameleon-store 主要有以下核心概念
通过 chameleon-store
创建的Store
实例,方法如下ChameleonStore.createStore(options: Object): Object
更多参见数据管理。
可以通过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例如
module.exports = [
{
method: ['get', 'post'],
path: '/api/getMessage',
controller: function (req, res, next) {
res.json({
total: 0,
message: [{
name: 'Hello chameleon!'
}]
});
}
}
]
chameleon的其他工程化配置统一收敛在项目根目录下的chameleon.config.js
文件在该文件中可以使用全局对象cml的api去操作配置对象。例如
配置当前项目支持的端
cml.config.merge({
platforms: ['web','wx'],
});
配置是否进行文件压缩
cml.config.merge({
web: {
dev: {
minimize: true
}
}
});
配置资源发布路径分离线上和线下的资源路径。
cml.config.merge({
web: {
build: {
publicPath: "http://www.chameleon.com/static"
}
}
});
更多配置参见工程配置
5 渐进式跨端
如果你既想一套代码运行多端又不用大刀阔斧的重构项目可以将多端重用组件用Chameleon开发直接在原有项目里面调用。参见导入与导出。也有如下手把手实例进行参考
6 端渲染能力接入
如果你需要跨native端渲染则需要接入chameleon SDK目前支持的渲染引擎是 weex即将支持 react native使用时二者选其一作为项目的 native 渲染引擎。chameleon SDK包括对原生组件和本地api能力的扩展对性能和稳定性的优化。使用方式可以参见Android Chameleon SDK 与IOS Chameleon SDK。
热门评论
这是什么问题,希望大佬解决一下,谢谢
我 npm i -g chameleon-tool 安装成功了,但是执行cml-v总是报command not found: cml
想问下这是什么原因?