CML 遷移指南

2020-05-14 14:20 更新

CML 作為真正讓一套代碼運(yùn)行多端的框架,提供標(biāo)準(zhǔn)的 MVVM 模式,統(tǒng)一開發(fā)各類終端。

同時(shí),擁有各端獨(dú)立的運(yùn)行時(shí)框架(Runtime)、數(shù)據(jù)管理(Store)、組件庫(UI)、接口(API)。

此外,CML 在跨端能力加強(qiáng)、能力統(tǒng)一、表現(xiàn)一致等方面做了許多工作。

今天,為了讓大家的項(xiàng)目優(yōu)雅升級(jí),快速接入,給你帶來一份豐盛的CML 遷移指南~

目錄結(jié)構(gòu)

和微信小程序一樣,CML 包含一個(gè)描述整體程序的 app 和多個(gè)描述各自頁面的 pages。

小程序目錄結(jié)構(gòu)

.
├── components // 包含各個(gè)組件
├── pages // 包含各個(gè)頁面
├── app.js  // 應(yīng)用啟動(dòng)入口
├── app.json // 全局配置
├── app.wxss // 全局樣式
└── project.config.json // 項(xiàng)目配置文件

cml 目錄結(jié)構(gòu)

.
├── dist // 各個(gè)端構(gòu)建結(jié)果
│   ├── tt
│   ├── qq
│   ├── alipay
│   ├── baidu
│   ├── wx
│   ├── web
│   ├── weex
│   └── config.json // 跨端配置map映射表
├── node_modules // 第三方庫
├── mock // 模擬 接口數(shù)據(jù) 和 模板數(shù)據(jù)
├── src  // 源代碼開發(fā)目錄
│   ├── app // 應(yīng)用啟動(dòng)入口
│   ├── assets // 靜態(tài)資源
│   ├── components // 包含組件
│   ├── pages  // 包含頁面
│   ├── store //數(shù)據(jù)管理
│   └── router.config.json // 路由配置文件
├── chameleon.config.js // 項(xiàng)目配置文件
└── package.json // npm包配置文件

如何修改配置

在小程序項(xiàng)目里面,分為:

小程序 —— 項(xiàng)目配置

可以在項(xiàng)目根目錄使用 project.config.json 文件對(duì)項(xiàng)目進(jìn)行配置。

配置示例:

{
  "miniprogramRoot": "./src",
  "debugOptions": {}
}

小程序 —— 全局配置

小程序根目錄下的 app.json 文件用來對(duì)微信小程序進(jìn)行全局配置,決定頁面文件的路徑、窗口表現(xiàn)、設(shè)置網(wǎng)絡(luò)超時(shí)時(shí)間、設(shè)置多 tab 等

配置示例:

{
  "pages": ["pages/index/index", "pages/logs/index"],
  "window": {
    "navigationBarTitleText": "Demo"
  },
  "networkTimeout": {
    "request": 10000,
    "downloadFile": 10000
  }
}

小程序 —— 頁面配置

每一個(gè)小程序頁面也可以使用 .json 文件來對(duì)本頁面的窗口表現(xiàn)進(jìn)行配置。

頁面的配置只能設(shè)置 app.json 中部分 window 配置項(xiàng)的內(nèi)容,頁面中配置項(xiàng)會(huì)覆蓋 app.json 的 window 中相同的配置項(xiàng)。

配置示例:

{
  "navigationBarBackgroundColor": "#ffffff",
  "navigationBarTextStyle": "black",
  "navigationBarTitleText": "微信接口功能演示",
  "backgroundColor": "#eeeeee",
  "backgroundTextStyle": "light"
}

同樣,在 CML 項(xiàng)目里面,分為:

cml —— 項(xiàng)目配置

chameleon.config.js 為項(xiàng)目的配置文件,你可以定制化構(gòu)建,比如是否帶 hash,是否 壓縮等等。

配置示例:

// 設(shè)置靜態(tài)資源的線上路徑
const publicPath = '//www.static.chameleon.com/static';
// 設(shè)置 API 請(qǐng)求前綴
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 項(xiàng)目 app 目錄下的 app.cml 文件的 <script cml-type="json" /> 用來對(duì) CML 應(yīng)用 進(jìn)行全局配置,具有跨端配置和差異化的能力

配置示例:

<script cml-type="json">
{
  "base": {
    "window": {
      "navigationBarTitleText": "各個(gè)端共同title",
    },
    "permission": {
      "scope.userLocation": {
        "desc": "你的位置信息將用于小程序位置接口的效果展示"
      }
    }
  },
  "wx": {
    "window": {
      "backgroundTextStyle":"light",
      "navigationBarBackgroundColor": "#fff",
      "navigationBarTitleText": "差異化 title",
      "navigationBarTextStyle":"black"
    }
  },
  "baidu": {
    "window": {
      "backgroundTextStyle": "light"
    }
  },
  "alipay": {
      "window": {
        "defaultTitle": "Chameleon"
      }
  }
}
</script>

cml —— 頁面/組件配置

通過 usingComponents 配置 組件路徑 注冊(cè)引用的組件。

配置示例:

<script cml-type="json">
{
  "base": {
    "usingComponents": {
      "navi": "/components/navi/navi",
      "navi-npm": "cml-test-ui/navi/navi"
    }
  },
  "wx": {
  },
  "alipay": {
  },
  "baidu": {
  },
  "web": {
  },
  "weex": {
  }
}
</script>

如何使用路由能力

小程序配置路由

app.json 配置項(xiàng)列表的 pages 字段用于指定小程序由哪些頁面組成,每一項(xiàng)都對(duì)應(yīng)一個(gè)頁面的 路徑+文件名 信息。

數(shù)組的第一項(xiàng)代表小程序的初始頁面(首頁)。新增/減少頁面,需要對(duì) pages 數(shù)組進(jìn)行修改。

如果項(xiàng)目有 pages/index/index.wxml、pages/logs/logs.wxml 兩個(gè)頁面,則需要在 app.json 中寫

{
  "pages": ["pages/index/index", "pages/logs/logs"]
}

cml 配置路由

src/router.config.json 是路由的配置文件,CML 內(nèi)置了一套各端統(tǒng)一的路由配置方式。相應(yīng)有 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 框架會(huì)自動(dòng)去尋找對(duì)于位置的 .cml 文件進(jìn)行處理。

小程序使用路由

  • 打開新頁面:調(diào)用 APIwx.navigateTo
  • 頁面重定向:調(diào)用 APIwx.redirectTo
  • 頁面返回:調(diào)用 APIwx.navigateBack
  • 打開另一個(gè)小程序:調(diào)用 APIwx.navigateToMiniProgram
  • 返回到上一個(gè)小程序:調(diào)用 APIwx.navigateBackMiniProgram

cml 使用路由

依據(jù)統(tǒng)一資源索引 URI,自適應(yīng)打開不同環(huán)境同一路由 PATH:

  • 打開新頁面:調(diào)用 chameleon-apicml.navigateTo
  • 頁面重定向:調(diào)用 chameleon-apicml.redirectTo
  • 頁面返回:調(diào)用 chameleon-apicml.navigateBack
  • 打開另一個(gè)跨端應(yīng)用:調(diào)用 chameleon-apicml.open
  • 返回到上一個(gè)跨端應(yīng)用:調(diào)用 chameleon-apicml.close

如何注冊(cè)

如何注冊(cè)程序

小程序注冊(cè)程序

在小程序項(xiàng)目里面,App() 函數(shù)用來注冊(cè)一個(gè)小程序。接受一個(gè) Object 參數(shù),其指定小程序的生命周期回調(diào)等。

示例代碼

App({
  onLaunch(options) {
    // Do something initial when launch.
  },
  globalData: 'I am global data',
});

cml 注冊(cè)程序

示例代碼

<script>
import store from '../store/index.js';
import routerConfig from '../router.config.json';

class App {
  data = {
    store,
    routerConfig,
  };
  created(res) {}
}

export default new App();
</script>

細(xì)心的你會(huì)發(fā)現(xiàn),

小程序中app.json app.js app.wxss和 src/app/app.cml的對(duì)應(yīng)關(guān)系如下

小程序 app.jsCML 項(xiàng)目 src/app/app.cml
app.js<script></script>
app.wxss<style></style>
app.json<script cml-type="json"></script>

如何注冊(cè)頁面

小程序注冊(cè)頁面

在小程序項(xiàng)目里面,Page(Object) 函數(shù)用來注冊(cè)一個(gè)頁面。接受一個(gè) Object 類型參數(shù),其指定頁面的初始數(shù)據(jù)、生命周期回調(diào)、事件處理函數(shù)等。

示例代碼:

// index.js
Page({
  data: {
    text: 'This is page data.',
  },
  changeText: function(e) {
    // sent data change to view
    this.setData({
      text: 'CML',
    });
  },
});

cml 注冊(cè)頁面

示例代碼

<script>
class Index {
  data = {
    text: 'Chameleon',
  };
  methods = {
    changeText: function(e) {
      // sent data change to view
      this.text = 'CML';
    },
  };
  computed = {};
  watch = {};
}
export default new Index();
</script>

如何注冊(cè)組件

小程序注冊(cè)組件

在小程序項(xiàng)目里面, Component(Object) 構(gòu)造器可用于定義組件,調(diào)用 Component 構(gòu)造器時(shí)可以指定組件的屬性、數(shù)據(jù)、方法等。

示例代碼

Component({
  properties: {
    myProperty: {
      // 屬性名
      type: String, // 類型(必填)
      value: '', // 屬性初始值(可選)
    },
    myProperty2: String, // 簡化的定義方式
  },
  data: {
    text: '',
  }, // 私有數(shù)據(jù),可用于模板渲染

  // 生命周期函數(shù),可以為函數(shù),或一個(gè)在methods段中定義的方法名
  attached() {},
  ready() {},
  methods: {
    onMyButtonTap() {
      this.setData({
        // 更新屬性和數(shù)據(jù)的方法與更新頁面數(shù)據(jù)的方法類似
        text: 'wx',
      });
    },
  },
});

cml 注冊(cè)組件

示例代碼

<script>
class MyComponent {
  props = {
    myProperty: {
      // 屬性名
      type: String, // 類型(必填)
      default: '', // 屬性初始值(可選)
    },
    myProperty2: String, // 簡化的定義方式
  };
  data = {
    text: '',
  }; // 私有數(shù)據(jù),可用于模板渲染

  beforeMount() {}
  mounted() {}
  methods = {
    onMyButtonTap() {
      this.text = 'cml';
    },
  };
  computed = {};
  watch = {};
}
export default new MyComponent();
</script>

如何聲明生命周期

統(tǒng)一各端應(yīng)用生命周期的定義,是跨端框架的重要組成,也是遷移的必經(jīng)之路。

小程序聲明生命周期

可以在 App(Object)、Page(Object)、Component(Object) 傳入Object參數(shù),其指定小程序的生命周期回調(diào)等

代碼示例

// index.js
Page({
  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 /> 代碼塊返回的對(duì)象實(shí)例,其指定生命周期回調(diào)

示例代碼

<script>
class Index {
  beforeCreate(query) {
    // data數(shù)據(jù)掛載到this根節(jié)點(diǎn)上之前,以及methods所有方法掛載到實(shí)例根節(jié)點(diǎn)之前
    // 注意:只用頁面的 beforeCreate鉤子 會(huì)返回頁面query
    console.log('App beforeCreate: 打開當(dāng)前頁面路徑中的參數(shù)是 ', query);
  }
  created() {
    // data,methods里面的這些events掛載完成
    console.log('App created');
  }
  beforeMount() {
    // 開始掛載已經(jīng)編譯完成的cml到對(duì)應(yīng)的節(jié)點(diǎn)時(shí)
    console.log('App beforeMount');
  }
  mounted() {
    // cml模板編譯完成,且渲染到dom中完成,在整個(gè)生命周期中只執(zhí)行一次
    console.log('App mounted');
  }
  beforeDestroy() {
    // 實(shí)例銷毀前
    console.log('App beforeDestroy');
  }
  destroyed() {
    // 實(shí)例銷毀后
    console.log('App destroyed');
  }
}
export default new Index();
</script>

App 生命周期 映射

小程序 app.js中的生命周期 -> cml src/app/app.cml

小程序CML
onLaunchbeforeCreate
onShowmounted
onHidedestroyed

Page 生命周期 映射

小程序 Page()中的生命周期 -> cml src/pages/mypage/mypage.cml

小程序CML
onLoadbeforeCreate
onShowmounted
onUnloaddestroyed
onReady生命周期多態(tài)
onHide生命周期多態(tài)
onShareAppMessage生命周期多態(tài)

Component 生命周期 映射

小程序 Component()中的生命周期 -> cml src/components/mycomponent/mycomponent.cml

小程序CML
createdcreated
attachedbeforeMount
readymounted
detacheddestroyed

生命周期總結(jié)

每個(gè) CML 實(shí)例(App、Page、Component)在被創(chuàng)建時(shí)都要經(jīng)過一系列的初始化過程 ————

例如,需要設(shè)置數(shù)據(jù)監(jiān)聽、編譯模板、將實(shí)例掛載到 CML 節(jié)點(diǎn)并在數(shù)據(jù)變化時(shí)更新 CML 節(jié)點(diǎn)等。同時(shí)在這個(gè)過程中也會(huì)運(yùn)行一些叫做生命周期鉤子的函數(shù),這給開發(fā)者在不同階段添加自己的代碼的機(jī)會(huì)。

CML 為 App、Page、Component 提供了一系列生命周期事件,保障應(yīng)用有序執(zhí)行。

另外,如果你想使用某個(gè)端特定的生命周期,你可以從業(yè)務(wù)出發(fā)使用生命周期多態(tài)。

數(shù)據(jù)如何響應(yīng)到視圖

如今,雙向數(shù)據(jù)綁定&單向數(shù)據(jù)流 已深入開發(fā)者日常,MVMM 開發(fā)模式算是框架標(biāo)配。

數(shù)據(jù)綁定、條件渲染、列表渲染是如何書寫的呢?

示例代碼

小程序使用數(shù)據(jù)響應(yīng)

<!--wxml-->
<view class="scroller-wrap">
  <!--數(shù)據(jù)綁定-->
  <view>{{message}}</view>
  <!--條件渲染-->
  <view wx:if="{{view == 'WEBVIEW'}}">WEBVIEW</view>
  <view wx:elif="{{view == 'APP'}}">APP</view>
  <view wx:else="{{view == 'MINA'}}">MINA</view>
  <!--列表渲染-->
  <view wx:for="{{array}}" wx:for-index="index" wx:for-item="item">{{item}}</view>
</view>
// page.js
Page({
  data: {
    message: 'Hello MINA!',
    view: 'MINA',
    array: [1, 2, 3, 4, 5],
  },
  onLoad() {
    this.setData({
      message: 'wx',
    });
  },
});

cml 使用數(shù)據(jù)響應(yīng)

<template>
  <!--index.cml-->
  <view class="scroller-wrap">
    <!--數(shù)據(jù)綁定-->
    <view>{{ message }}</view>
    <!--條件渲染-->
    <view c-if="{{view == 'WEBVIEW'}}">WEBVIEW</view>
    <view c-else-if="{{view == 'APP'}}">APP</view>
    <view c-else="{{view == 'MINA'}}">MINA</view>
    <!--列表渲染-->
    <view c-for="{{array}}" c-for-index="index" c-for-item="item">{{ item }}</view>
  </view>
</template>
<script>
class Index {
  data = {
    message: 'Hello MINA!',
    view: 'MINA',
    array: [1, 2, 3, 4, 5],
  };

  beforeCreate() {
    this.message = 'cml';
  }
}
export default new Index();
</script>

數(shù)據(jù)響應(yīng)總結(jié)

CML 運(yùn)行時(shí)框架 提供了跨端響應(yīng)式數(shù)據(jù)綁定系統(tǒng),當(dāng)做數(shù)據(jù)修改的時(shí)候,只需要在邏輯層修改數(shù)據(jù),視圖層就會(huì)做相應(yīng)的更新。

只需要將 view<-->model 交互部分邏輯,作簡單遷移,便可使它成為跨多端的數(shù)據(jù)響應(yīng)系統(tǒng)。

事件交互

CML 支持一些基礎(chǔ)的事件,保障各端效果(類型、綁定、事件對(duì)象)一致運(yùn)行。

示例代碼

小程序使用事件

<!--wxml-->
<view id="tapTest" data-hi="WeChat" bindtap="tapName">Click me!</view>
// page.js
Page({
  tapName(event) {
    console.log(event);
  },
});

cml 使用事件

<template>
  <view id="tapTest" data-hi="WeChat" c-bind:tap="tapName">
    <text>Click me!</text>
  </view>
</template>
<script>
class Index {
  methods = {
    tapName(e) {
      // 打印事件對(duì)象
      console.log('事件對(duì)象:', e);
    },
  };
}
export default new Index();
</script>

事件使用總結(jié)

同時(shí),還支持自定義事件,用于父子組件之間的通信。

另外,如果你想要使用某個(gè)端特定的事件,CML 并不會(huì)限制你的自由發(fā)揮,你可以從業(yè)務(wù)出發(fā)使用多態(tài)組件 或者多態(tài)接口差異化實(shí)現(xiàn)功能。

布局和外觀

各端描述 布局和外觀 的層疊樣式表(CSS)實(shí)現(xiàn)存在差異,包括不限于 布局、盒模型、定位、文本。

所以,CML 框架內(nèi)置跨端一致性基礎(chǔ)樣式能力。

并且,定義了用于描述頁面的樣式規(guī)范CMSS(Chameleon Style Sheet)。

如何導(dǎo)入外部樣式

使用 @import 語句可以導(dǎo)入外聯(lián)樣式表,@import 后跟需要導(dǎo)入的外聯(lián)樣式表的相對(duì)路徑,用 ; 表示語句結(jié)束。

小程序?qū)胪獠繕邮?/h3>

示例代碼:

/** common.wxss **/
.small-p {
  padding: 5px;
}
/** app.wxss **/
@import 'common.wxss';
.middle-p {
  padding: 15px;
}

cml 導(dǎo)入外部樣式

詳細(xì)文檔

示例代碼:

/** common.css **/
.small-p {
  padding: 5px;
}
<!-- app.cml -->
<style>
@import './common.css';
.middle-p {
  padding: 15 cpx;
}
</style>

樣式使用總結(jié)

同時(shí),為了統(tǒng)一多端尺寸單位,呈現(xiàn)效果一致,同時(shí)頁面響應(yīng)式布局,CML 項(xiàng)目統(tǒng)一采用 cpx 作為尺寸單位,規(guī)定以屏幕 750px(占滿屏幕)視覺稿作為標(biāo)準(zhǔn)。

而且,各端樣式表擁有的能力不盡相同,是項(xiàng)目遷移的主要陣地之一。

另外,如果你想要使用某個(gè)端特定的樣式能力,CML 并不會(huì)限制你的自由發(fā)揮,你可以從業(yè)務(wù)出發(fā)使用樣式多態(tài)

注意:由于 CML 應(yīng)用是跨多端 Web Native 小程序框架,如果需要跨 Native,必須使用flexbox進(jìn)行樣式布局?。?!

組件

CML 項(xiàng)目一切皆組件。組件是視圖的基本組成單元。

框架為開發(fā)者提供了一系列基礎(chǔ)組件,開發(fā)者可以通過組合這些基礎(chǔ)組件進(jìn)行快速開發(fā)。

如:

<template>
  <view>
    <view>view 基礎(chǔ)組件</view>
    <text>text 基礎(chǔ)組件</text>
  </view>
</template>

同時(shí),CML 支持簡潔的組件化編程。

自定義組件

開發(fā)者可以將頁面內(nèi)的功能模塊抽象成自定義組件,以便在不同的頁面中重復(fù)使用。自定義組件在使用時(shí)與基礎(chǔ)組件非常相似。

如何創(chuàng)建自定義組件

小程序創(chuàng)建自定義組件

代碼示例:

Component({
  properties: {
    // 這里定義了innerText屬性,屬性值可以在組件使用時(shí)指定
    innerText: {
      type: String,
      value: 'default value',
    },
  },
  data: {
    // 這里是一些組件內(nèi)部數(shù)據(jù)
    someData: {},
  },
  methods: {
    // 這里是一個(gè)自定義方法
    customMethod() {},
  },
});

cml 創(chuàng)建自定義組件

示例代碼

<script>
class MyComponent {
  props = {
    // 這里定義了innerText屬性,屬性值可以在組件使用時(shí)指定
    innerText: {
      type: String,
      value: 'default value',
    },
  };
  data = {
    // 這里是一些組件內(nèi)部數(shù)據(jù)
    someData: {},
  };
  methods = {
    // 這里是一個(gè)自定義方法
    customMethod() {},
  };
  computed = {};
  watch = {};
}
export default new MyComponent();
</script>

如何使用自定義組件

使用已注冊(cè)的自定義組件前,首先要進(jìn)行引用聲明。此時(shí)需要提供每個(gè)自定義組件的標(biāo)簽名和對(duì)應(yīng)的自定義組件文件路徑。

小程序使用自定義組件

代碼示例:

在 page.json 中進(jìn)行引用聲明

{
  "usingComponents": {
    "component-tag-name": "path/to/the/custom/component"
  }
}

在 page.wxml 中使用

<view>
  <!-- 以下是對(duì)一個(gè)自定義組件的引用 -->
  <component-tag-name inner-text="Some text"></component-tag-name>
</view>

cml 使用自定義組件

代碼示例:

在 page.cml中<script cml-type='json' />進(jìn)行引用聲明

<script cml-type="json">
{
  "base": {
      "usingComponents": {
        "component-tag-name": "path/to/the/custom/component"
      }
  }
}
</script>

在 page.cml中<template />使用

<template>
  <view>
    <!-- 以下是對(duì)一個(gè)自定義組件的引用 -->
    <component-tag-name inner-text="Some text"></component-tag-name>
  </view>
</template>

如何實(shí)現(xiàn)父子組件事件通信

事件系統(tǒng)是組件間通信的主要方式之一。自定義組件可以觸發(fā)任意的事件,引用組件的頁面可以監(jiān)聽這些事件。

小程序組件通信

代碼示例:

<!-- 頁面 page.wxml -->
<view>
  <my-component bindcustomevent="onMyEvent"></my-component>
</view>
// 頁面 page.js
Page({
  methods: {
    onMyEvent(e) {
      console.log(e.detail); // 自定義組件觸發(fā)事件時(shí)提供的detail對(duì)象
    },
  },
});
<!-- 組件 my-component.wxml -->
<view>
  <button bindtap="onTap">點(diǎn)擊這個(gè)按鈕將觸發(fā)“myevent”事件</button>
</view>
// 組件 my-component.js
Component({
  methods: {
    onTap() {
      this.triggerEvent('customevent', {}); // 觸發(fā) 自定義組件事件
    },
  },
});

cml 組件通信

代碼示例:

<!-- 頁面 page.cml -->
<template>
  <view>
    <my-component c-bind:customevent="onMyEvent"></my-component>
  </view>
</template>
<script>
class Index {
  methods = {
    // 這里是一個(gè)自定義方法
    onMyEvent(e) {
      console.log(e.detail); // 自定義組件觸發(fā)事件時(shí)提供的detail對(duì)象
    },
  };
}
export default new Index();
</script>
<script cml-type="json">
{
  "base": {
      "usingComponents": {
        "my-component": "path/to/the/custom/component"
      }
  }
}
</script>
<!-- 頁面 path/to/the/custom/component.cml -->
<template>
  <view>
    <button c-bind:tap="onTap">點(diǎn)擊這個(gè)按鈕將觸發(fā)“myevent”事件</button>
  </view>
</template>
<script>
class MyComponent {
  methods = {
    // 這里是一個(gè)自定義方法
    onTap() {
      this.$cmlEmit('customevent', {}); // 觸發(fā) 自定義組件事件
    },
  };
}
export default new MyComponent();
</script>
<script cml-type="json">
{
}
</script>

組件使用總結(jié)

和小程序一樣,cml框架 提供了大量內(nèi)置組件和擴(kuò)展組件,抹平多端差異,便于開發(fā)者通過組合這些組件,創(chuàng)建出強(qiáng)大的應(yīng)用程序。

擴(kuò)展組件需要額外引入。如:

<script cml-type="json">
{
  "base": {
      "usingComponents": {
        "c-dialog": "cml-ui/components/c-dialog/c-dialog"
      }
  }
}
</script>

在執(zhí)行 cml build 構(gòu)建打包時(shí),cml 框架 會(huì)按需打包引用的內(nèi)置組件和擴(kuò)展組件,為代碼瘦身。

內(nèi)置組件和擴(kuò)展組件都是支持跨多端的,對(duì)于一些沒有提供的某個(gè)端的組件,可以通過多態(tài)組件來實(shí)現(xiàn)。

如果希望使用小程序端的原生組件,那么可以在原生標(biāo)簽前加上 origin-*,CML 框架會(huì)渲染原生組件。

注意:origin-* 只能在灰度區(qū)文件中使用??!

如在 map.wx.cml 文件中使用原生地圖組件 <map/>:

<!-- map.wx.cml -->
<template>
  <origin-map
    id="map"
    longitude="113.324520"
    latitude="23.099994"
    controls="{{controls}}"
    bindcontroltap="controltap"
    style="width: 100%; height: 300px;"
  ></origin-map>
</template>

如何調(diào)用平臺(tái)接口能力

在小程序里面,可以通過微信原生 API,調(diào)起如獲取用戶信息,本地存儲(chǔ),支付功能等。

示例代碼

try {
  wx.setStorageSync('name', 'Hanks');
} catch (e) {
  console.error(e);
}

同樣,在 CML 項(xiàng)目里面可以這樣調(diào)用:

示例代碼

import cml from 'chameleon-api';
cml.setStorage('name', 'Hanks').then(
  (res) => {
    console.log(res);
  },
  function(e) {
    console.error(e);
  },
);

接口使用總結(jié)

CML 框架提供了豐富的多態(tài)接口,可以調(diào)起各端提供的原生能力,如系統(tǒng)信息、元素節(jié)點(diǎn)信息、動(dòng)畫效果、本地存儲(chǔ)、網(wǎng)絡(luò)請(qǐng)求、地理位置等。請(qǐng)參考API文檔。

chameleon-api 提供的接口都是支持跨多端的,對(duì)于一些沒有提供的某個(gè)端的原生接口,可以通過多態(tài)接口來調(diào)用。

遷移總結(jié)

CML 作為一端代碼運(yùn)行多端的框架,所有接口設(shè)計(jì)都考慮的是具備跨端要求的設(shè)計(jì),沒有使用任何一端的接口設(shè)計(jì)規(guī)范,而是全新一套框架,所以不要”想當(dāng)然“用微信小程序或者 vue 的接口來開發(fā) CML。

例如,如果你是微信小程序開發(fā)者,當(dāng)你想使用 tabbar 功能時(shí),可能會(huì)在app.json 里面配置,這是錯(cuò)誤的,這是微信特有模式,只在微信里面有效。在 cml 中請(qǐng)使用c-tabbar來實(shí)現(xiàn),這樣所有端都有效。

遷移實(shí)例

下面給出各端(vue、weex、小程序)遷移cml指南 以及 cml 導(dǎo)出組件到各端指南的具體遷移文檔:

  • 如何遷移一個(gè) Vue 項(xiàng)目到 chameleon
  • 如何遷移一個(gè) Weex 項(xiàng)目到 chameleon
  • 如何遷移一個(gè)微信小程序到 chameleon


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)