導(dǎo)入與導(dǎo)出

2020-05-14 14:20 更新

導(dǎo)出

即 將 CML 可重用組件導(dǎo)出給普通項(xiàng)目使用,或者說 某端普通項(xiàng)目里面使用 CML 可重用組件。

導(dǎo)入

即 在 CML 可重用項(xiàng)目中導(dǎo)入普通項(xiàng)目產(chǎn)出的組件,或者說 可重用代碼 CML 項(xiàng)目使用某端普通組件。

使用方式

終端項(xiàng)目框架導(dǎo)入導(dǎo)出說明
微信原始項(xiàng)目已支持
微信MPX待支持
WebVue已支持
WebReact待支持
Web其他支持導(dǎo)入,不支持導(dǎo)出
NativeVue已支持
NativeReact待支持
NativeFlutter待支持
NativeObjective-C MVVM框架待支持
NativeAndroid Java MVVM框架待支持

漸進(jìn)式接入

跨端有 2 種需求。

  • 整個(gè)項(xiàng)目一套代碼實(shí)現(xiàn):第一種業(yè)務(wù)層需求在各端環(huán)境高度類似,原本需要針對(duì)不同端重復(fù)開發(fā)、重復(fù)測(cè)試,那么使用 CML 將整個(gè)項(xiàng)目”從上至下“都用一套代碼運(yùn)行,針對(duì)各端底層極個(gè)別差異化實(shí)現(xiàn)(使用多態(tài)協(xié)議)。 - 場(chǎng)景舉例:首頁官網(wǎng)、列表詳情頁等
  • 僅組件一套代碼運(yùn)行:第二種是各端頁面需求不一致,卻有共同的組件需要重復(fù)開發(fā)、重復(fù)測(cè)試,各個(gè)端用各自原本框架開發(fā)(或者使用 CML 方案),使用一套代碼開發(fā)公用組件,然后各個(gè)端可以使用公用組件實(shí)現(xiàn)業(yè)務(wù) - 場(chǎng)景舉例:分享組件、支付組件、地圖組件
整個(gè)項(xiàng)目一套代碼實(shí)現(xiàn)僅組件一套代碼運(yùn)行

webpack 集成

注:內(nèi)部 webpack 插件版本基于 webpack@3.12.0 開發(fā)選擇,暫不兼容 webpack4。

通過以下步驟,可以讓 webpack 項(xiàng)目中使用 CML 的任意組件。

  • 1 安裝 npm 包 npm i easy-chameleon chameleon-ui-builtin
  • 2 執(zhí)行腳本 node node_modules/\easy-chameleon/bin/index.js,該腳本會(huì)執(zhí)行檢測(cè),安裝未安裝的第三方 npm 包
  • 3 .babelrc 的 preset 添加 flow, CML 中用了 flow 語法,如果需要用到chameleon-api,建議配置babel-plugin-chameleon-import插件實(shí)現(xiàn)按需加載。例如:
{
  "presets": [
    "flow",
    ["env", {
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-0"
  ],
  "plugins": [
    "transform-vue-jsx",
    "transform-runtime",
    [
      "babel-plugin-chameleon-import", {
      "libraryName": "chameleon-api",
      "libraryDirectory": "src/interfaces",
      "libraryFileName": "index.js",
      "defaulLibraryDirectory": "",
      "defaulLibraryFileName": "index.js",
      }
    ]
  ]
}

  • 4 入口代碼中,引入代碼 import 'easy-chameleon/entry/web_global.js';
  • 5 修改 webpack 配置文件,easy-chameleon提供了getConfig方法獲取 webpack 配置 ,利用webpack-merge將項(xiàng)目原有 webpack 配置與getConfig方法獲取的配置進(jìn)行合并,例如:const merge = require('webpack-merge') const {getConfig} = require('easy-chameleon'); devWebpackConfig = merge(devWebpackConfig, getConfig({ cmlType: 'web', media: 'dev', hot: true, disableExtract: false, context: path.join(__dirname,'../'), cmss: { rem: false, scale: 0.5 } })) getConfig方法參數(shù) getConfig(Object object)參數(shù)類型默認(rèn)值必填說明cmlTypeString是端類型,可選值為web|wx|weexmediaString是構(gòu)建模式,可選值為dev|buildhotBooleanfalse否是否開啟熱更新,只在web端生效disableExtractBooleanfalse否不提取css文件cmssObject否cmss處理的配置,參見下方cmss對(duì)象屬性列表wxConfigObject否微信端構(gòu)建配置,參見下方wxConfig對(duì)象屬性列表

cmss 對(duì)象屬性列表

參數(shù)類型默認(rèn)值必填說明
remBooleantrue將cpx以75cpx=1rem為標(biāo)準(zhǔn)轉(zhuǎn)換成rem
scaleNumber0.5當(dāng)rem為false時(shí),scale將生效,將cpx乘以scale為px

wxConfig 對(duì)象屬性列表

參數(shù)類型默認(rèn)值必填說明
entryArray[String]指定輸出的組件入口,以項(xiàng)目根目錄下的相對(duì)路徑,會(huì)尋找指定路徑下的cml文件進(jìn)行編譯
outputPathString輸出路徑


組件導(dǎo)出

這里介紹的是第二種場(chǎng)景,將 CML 組件導(dǎo)出到某個(gè)端使用。

介紹

為了讓開發(fā)者更自由地使用 CML 我們提供組件導(dǎo)出的形式,讓開發(fā)者可以在任意端原有項(xiàng)目中使用通過 CML 開發(fā)的組件。我們用 Web 端和小程序端舉例,按正常開發(fā)模式我們需要分別維護(hù)著 4 套代碼(web、wx、alipay、baidu),在某一個(gè)業(yè)務(wù)場(chǎng)景下需要開發(fā)一個(gè)時(shí)間選擇器的組件,原有模式下我們需要每個(gè)端獨(dú)自開發(fā),而對(duì)于這種公共的組件,就可以選擇使用 CML 去維護(hù),通過 CML 開發(fā),只需要維護(hù)一套組件代碼,最后通過組件導(dǎo)出就可以在各個(gè)端進(jìn)行使用了。這樣的模式完全利用了 CML 的跨端優(yōu)勢(shì),大大降低了代碼開發(fā)維護(hù)成本。

組件導(dǎo)出開發(fā)模式: 

命令行

  • cml web export 執(zhí)行 Web 端組件導(dǎo)出
  • cml weex export 執(zhí)行 Weex 端組件導(dǎo)出
  • cml wx export 執(zhí)行 wx 端組件導(dǎo)出
  • cml alipay export 執(zhí)行 alipay 端組件導(dǎo)出
  • cml baidu export 執(zhí)行 baidu 端組件導(dǎo)出

配置

在 chameleon.config.js 中增加 export 配置,即可自定義組件導(dǎo)出配置,可配置項(xiàng)參考下表:

配置項(xiàng)類型說明
entryArray組件導(dǎo)出的入口目錄,項(xiàng)目根目錄的相對(duì)路徑
outputPathString組件導(dǎo)出目錄,絕對(duì)路徑
publicPathString公共資源地址
hashBoolean導(dǎo)出文件名是否帶hash,默認(rèn)true
minimizeBoolean導(dǎo)出文件名是否壓縮,默認(rèn)true
disableExtractBoolean不拆分css,默認(rèn)false
externalsObject導(dǎo)出依賴分離,可配置不導(dǎo)出部分依賴,而使用外部依賴

以 Web 端為例,配置如下:

cml.config.merge({
  web: {
    dev: {},
    build: {},
    export: {
      entry: ['src/components'],
      publicPath: 'https://static.chameleon.com/static',
    },
  },
});

導(dǎo)出組件

CML 組件導(dǎo)出目錄結(jié)構(gòu)如下:

├── dist
|   ├── export
│   │   ├── platform (web、weex、wx、alipay、baidu ...)
│   │   │   ├── common
|   │   │   │   ├── web_global.js [僅導(dǎo)出web端組件時(shí)存在,需要在入口文件中引用]
|   │   │   │   ├── web_global.css [會(huì)在web_global.js中引用]
│   │   │   ├── 組件目錄
│   │   │   └── 資源目錄

下面是在 webpack+vue 環(huán)境下引用 CML 導(dǎo)出組件的示例:

假設(shè)目前已經(jīng)通過 CML 項(xiàng)目導(dǎo)出了 c-header 組件,將組件移動(dòng)到 webpack+vue 的環(huán)境后,需要進(jìn)行一下幾步操作:

  1. 假設(shè)是 Web 端組件,則首先需要在入口文件中引用 web_global.js
  2. 在需要使用組件的地方引用組件即可

導(dǎo)出組件公共依賴分離

當(dāng)組件 A 和組件 B 同時(shí)依賴于公共模塊 C 時(shí),普通導(dǎo)出會(huì)將 C 打包到導(dǎo)出的 A、B 組件代碼中,此時(shí)使用 A、B 組件相當(dāng)于有兩份模塊 C 的代碼,為了優(yōu)化這一問題,導(dǎo)出組件提供分離公共依賴配置,即將模塊 C 作為第三方依賴,在 A、B 組件導(dǎo)出時(shí)將模塊 C 分離,在使用時(shí)依賴模塊 C。

這里以chameleon-runtime為例,首先將chameleon-runtime編譯出僅 Web 端使用的版本chameleon-runtime-web,在導(dǎo)出 web 組件配置部分增加相關(guān)配置,然后導(dǎo)出的組件在依賴chameleon-runtime的部分就會(huì)變成依賴chameleon-runtime-web,最后在使用的項(xiàng)目中下載chameleon-runtime-web即可使用。

cml.config.merge({
  web: {
    export: {
      entry: ['src/components'],
      publicPath: 'https://static.chameleon.com/static',
      externals: {
        'chameleon-runtime': 'chameleon-runtime-web',
      },
    },
  },
});

Bug & Tips

  • .babelrc 配置中去掉module: false
  • 由于生產(chǎn)模式組件為編譯后的模塊,所以盡量使用線上資源

Web

組件開發(fā)模式

Web 端組件接入

chameleon 允許在 Web 端多態(tài)組件中直接引入原生 vue 組件,一方面是為了增加代碼重用度,另一方面則是方便漸進(jìn)式地遷移使用 CML

為什么要接入 Web 端組件

chameleon 作為跨端框架,將各端相同性及差異性進(jìn)行統(tǒng)一封裝形成 CML 的規(guī)范,但即使是這樣,我們也沒有辦法百分百地避免差異,這樣的差異可能來自產(chǎn)品的要求、技術(shù)的實(shí)現(xiàn)等等,由此 CML 提出了多態(tài)組件協(xié)議,在多態(tài)組件實(shí)現(xiàn)中,直接引用原生組件,降低開發(fā)成本。

怎么引入 Web 端組件

在 CML 中使用組件只需要在組件配置中寫入依賴的子組件,下面是 Web 端組件引用 vue 單文件組件的示例:

<!-- index.cml -->
<template>
  <v-list></v-list>
</template>
...
<script cml-type="json">
{
  "base": {
    "usingComponents": {
      "v-list": "/components/vue-components/v-list"
    }
  }
}
</script>
<!-- components/vue-components/v-list.vue -->
<template>
  <ul>
    <li v-for="l in list">{{ l }}</li>
  </ul>
</template>
<script>
export default {
  props: {
    list: {
      type: Array,
      default: function() {
        return [1, 2, 3, 4];
      },
    },
  },
};
</script>
需要注意的是組件路徑需要寫到.vue 層級(jí),但是不帶后綴。

Weex

組件開發(fā)模式 

Weex 端組件接入

chameleon 允許在 Weex 端多態(tài)組件中直接引入原生 vue 組件,一方面是為了增加代碼重用度,另一方面則是方便漸進(jìn)式地遷移使用 CML

為什么要接入 Weex 端組件

chameleon 作為跨端框架,將各端相同性及差異性進(jìn)行統(tǒng)一封裝形成 CML 的規(guī)范,但即使是這樣,我們也沒有辦法百分百地避免差異,這樣的差異可能來自產(chǎn)品的要求、技術(shù)的實(shí)現(xiàn)等等,由此 CML 提出了多態(tài)組件協(xié)議,在多態(tài)組件實(shí)現(xiàn)中,直接引用原生組件,降低開發(fā)成本。

怎么引入 Weex 端組件

第一類是 Weex 支持的原生組件,比如div text等,詳細(xì)請(qǐng)查看Weex 原生組件列表,如果這樣的組件已經(jīng)滿足開發(fā)需求,那么就可以直接使用了:

<!-- list.weex.cml -->
<template>
  <div>
    <text v-for="l in list">{{ l }}</text>
  </div>
</template>

第二類是原先封裝好的組件,首先你需要將組件復(fù)制到 CML 項(xiàng)目中,然后只需要在 CML 組件中聲明式引入該組件即可使用。 還是以list組件為例,假設(shè)原有封裝好的組件custom-list,目錄結(jié)構(gòu)如下:

<!-- index.cml -->
<template>
  <v-list></v-list>
</template>
...
<script cml-type="json">
{
  "base": {
    "usingComponents": {
      "v-list": "/components/vue-components/v-list"
    }
  }
}
</script>
<!-- components/vue-components/v-list.vue -->
<template>
  <ul>
    <li v-for="l in list">{{ l }}</li>
  </ul>
</template>
<script>
export default {
  props: {
    list: {
      type: Array,
      default: function() {
        return [1, 2, 3, 4];
      },
    },
  },
};
</script>
需要注意的是組件路徑需要寫到.vue 層級(jí),但是不帶后綴。

微信小程序

組件開發(fā)模式 

小程序組件接入

chameleon 允許在多態(tài)組件中引入原生微信小程序組件,對(duì)于已經(jīng)熟悉小程序組件開發(fā)的朋友將非常 easy,之前封裝的微信小程序組件可以直接使用,微信小程序相關(guān)的 ui 庫可以直接使用,微信小程序自帶的組件也可以直接使用。

為什么要接入微信小程序組件

多態(tài)組件存在的差異不過來自于各端需求不同,又或是各端實(shí)現(xiàn)方式的不同。微信小程序組件的接入跟第二個(gè)問題完美契合,在原有的小程序開發(fā)過程中或許已經(jīng)產(chǎn)出了常用組件,又或是使用著某個(gè)微信小程序的組件庫,當(dāng)使用 CML 進(jìn)行開發(fā)時(shí),避免了二次開發(fā)原有組件的成本。

#怎么引入微信小程序組件

第一類是微信小程序支持的組件,比如view text等,詳細(xì)請(qǐng)查看微信小程序組件列表,如果這樣的組件已經(jīng)滿足開發(fā)需求,那么就可以直接使用了:

<!-- list.wx.cml -->
<template>
  <view>
    <text v-for="l in list">{{ l }}</text>
  </view>
</template>

第二類是原有的組件,首先你需要將組件復(fù)制到 CML 項(xiàng)目中,然后只需要在 CML 組件中聲明式引入該組件即可使用。 還是以list組件為例,假設(shè)原有封裝好的微信小程序的組件custom-list,目錄結(jié)構(gòu)如下:

├── components                      // 組件文件夾
|   ├── custom-list
|   |   ├── custom-list.wxml
|   |   ├── custom-list.wxss
|   |   ├── custom-list.js
|   |   └── custom-list.json

那么,在 list.wx.cml 中可以直接引用:

<!-- list.wx.cml -->
<template>
  <custom-list list="{{list}}"></custom-list>
</template>
...
<script cml-type="json">
{
  "base": {
    "usingComponents": {
      "custom-list": "/components/custom-list/custom-list"
    }
  }
}
需要注意的是組件路徑需要寫到.wxml 層級(jí),但是不帶后綴。

第三類是微信小程序的組件庫,這里以iVew Webapp為例,首先需要將其代碼下載下來放到 CML 項(xiàng)目中,假設(shè)目錄結(jié)構(gòu)如下:

├── components                      // 組件文件夾
|   ├── iview
|   |   ├── action-sheet
|   |   |   ├── index.js
|   |   |   ├── index.json
|   |   |   ├── index.wxml
|   |   |   └── index.wxss
|   |   ├── alert
|   |   ├── avatar
|   |   └── ...

這里我們需要使用 action-sheet 組件只需要如下即可:

<!-- component.wx.cml -->
<template>
  <action-sheet></action-sheet>
</template>
...
<script cml-type="json">
{
  "base": {
    "usingComponents": {
      "action-sheet": "/components/iview/action-sheet/index"
    }
  }
}
需要注意的是組件路徑需要寫到.wxml 層級(jí),但是不帶后綴。

支付寶小程序

組件開發(fā)模式 

小程序組件接入

chameleon 允許在多態(tài)組件中直接引入支付寶小程序組件,如果你已經(jīng)封裝了支付寶小程序的組件,如果你已經(jīng)在用支付寶小程序的組件庫,不用擔(dān)心,在 CML 項(xiàng)目中你仍然可以使用。

為什么要接入支付寶小程序組件

多態(tài)組件存在的差異不過來自于各端需求不同,又或是各端實(shí)現(xiàn)方式的不同。支付寶小程序組件的接入跟第二個(gè)問題完美契合,在原有的小程序開發(fā)過程中或許已經(jīng)產(chǎn)出了常用組件,又或是使用著某個(gè)支付寶小程序的組件庫,當(dāng)使用 CML 進(jìn)行開發(fā)時(shí),避免了二次開發(fā)原有組件的成本。

怎么引入支付寶小程序組件

第一類是支付寶小程序支持的組件,比如view text等,詳細(xì)請(qǐng)查看支付寶小程序組件列表,如果這樣的組件已經(jīng)滿足開發(fā)需求,那么就可以直接使用了:

<!-- list.alipay.cml -->
<template>
  <view>
    <text v-for="l in list">{{ l }}</text>
  </view>
</template>

第二類是原有的組件,首先你需要將組件復(fù)制到 CML 項(xiàng)目中,然后只需要在 CML 組件中聲明式引入該組件即可使用。 還是以list組件為例,假設(shè)原有封裝好的支付寶小程序的組件custom-list,目錄結(jié)構(gòu)如下:

├── components                      // 組件文件夾
|   ├── custom-list
|   |   ├── custom-list.axml
|   |   ├── custom-list.acss
|   |   ├── custom-list.js
|   |   └── custom-list.json

那么,在 list.alipay.cml 中可以直接引用:

<!-- list.alipay.cml -->
<template>
  <custom-list list="{{list}}"></custom-list>
</template>
...
<script cml-type="json">
{
  "base": {
    "usingComponents": {
      "custom-list": "/components/custom-list/custom-list"
    }
  }
}
需要注意的是組件路徑需要寫到.axml 層級(jí),但是不帶后綴。

百度小程序

組件開發(fā)模式 

小程序組件接入

chameleon 允許在多態(tài)組件中直接引入百度小程序組件,如果你已經(jīng)封裝了百度小程序的組件,如果你已經(jīng)在用百度小程序的組件庫,不用擔(dān)心,在 CML 項(xiàng)目中你仍然可以使用。

為什么要接入百度小程序組件

多態(tài)組件存在的差異不過來自于各端需求不同,又或是各端實(shí)現(xiàn)方式的不同。百度小程序組件的接入跟第二個(gè)問題完美契合,在原有的小程序開發(fā)過程中或許已經(jīng)產(chǎn)出了常用組件,又或是使用著某個(gè)百度小程序的組件庫,當(dāng)使用 CML 進(jìn)行開發(fā)時(shí),避免了二次開發(fā)原有組件的成本。

怎么引入百度小程序組件

第一類是百度小程序支持的組件,比如view text等,詳細(xì)請(qǐng)查看百度小程序組件列表,如果這樣的組件已經(jīng)滿足開發(fā)需求,那么就可以直接使用了:

<!-- list.baidu.cml -->
<template>
  <view>
    <text v-for="l in list">{{ l }}</text>
  </view>
</template>

第二類是原有的組件,首先你需要將組件復(fù)制到 CML 項(xiàng)目中,然后只需要在 CML 組件中聲明式引入該組件即可使用。 還是以list組件為例,假設(shè)原有封裝好的百度小程序的組件custom-list,目錄結(jié)構(gòu)如下:

├── components                      // 組件文件夾
|   ├── custom-list
|   |   ├── custom-list.swan
|   |   ├── custom-list.css
|   |   ├── custom-list.js
|   |   └── custom-list.json

那么,在 list.baidu.cml 中可以直接引用:

<!-- list.baidu.cml -->
<template>
  <custom-list list="{{list}}"></custom-list>
</template>
...
<script cml-type="json">
{
  "base": {
    "usingComponents": {
      "custom-list": "/components/custom-list/custom-list"
    }
  }
}
需要注意的是組件路徑需要寫到.swan 層級(jí),但是不帶后綴。


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

掃描二維碼

下載編程獅App

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

編程獅公眾號(hào)