以小邏輯塊為單位,對(duì)照老代碼,以 cml 語(yǔ)法重寫,報(bào)錯(cuò)可修正
這樣可避免以下問(wèn)題:
1、大塊邏輯遷移會(huì)導(dǎo)致報(bào)錯(cuò)無(wú)法追查
2、直接 copy 會(huì)導(dǎo)致語(yǔ)法隱藏 bug 不可控(雖然 ide 沒有問(wèn)題,但真機(jī)調(diào)試出問(wèn)題)
請(qǐng)盡量按照 cml 語(yǔ)法或者類 vue 語(yǔ)法重寫遷移,避免語(yǔ)法糾錯(cuò)浪費(fèi)時(shí)間
cml init project
初始化后,CML 項(xiàng)目如下:
依具體情況配置構(gòu)建平臺(tái)和配置平臺(tái)基礎(chǔ)樣式。
可修改 chameleon.config.js 的 platforms 和 baseStyle 字段,如下:
假設(shè)有下面 ???? 結(jié)構(gòu)的 Weex 項(xiàng)目 weex-toolkit生成。
components下包含各個(gè)組件代碼,router.js下是路由配置,config是 Weex 項(xiàng)目的 webpack 構(gòu)建的基本配置
CML 的工程配置具體
Weex 項(xiàng)目 | CML 項(xiàng)目 |
---|---|
npm run dev | cml dev |
npm run build | cml build |
CML 項(xiàng)目中的 store 和 Weex 項(xiàng)目中的 store 文件下是對(duì)應(yīng)的。
假設(shè) vue 項(xiàng)目中某個(gè)組件
import { mapState } from 'vuex';
export default {
computed: mapState(['count']),
};
那么在 CML 項(xiàng)目中
import store from '../path/to/store';
class Index {
computed = store.mapState(['count']);
}
export default new Index();
假如 Weex 項(xiàng)目中入口文件 src/index.vue
<template>
<div id="app">
<router-view />
</div>
</template>
那么對(duì)應(yīng)著 CML 項(xiàng)目中的src/app/app.cml,這里的<app>會(huì)渲染成<router-view>對(duì)應(yīng)的某個(gè)路由;
<template>
<app store="{{store}}" router-config="{{routerConfig}}"></app>
</template>
weex項(xiàng)目中的路由 src/router.js
import Vue from 'vue';
import Router from 'vue-router';
import HelloWorld from '@/components/HelloWorld';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/helloworld',
name: 'HelloWorld',
component: HelloWorld,
},
],
});
cml項(xiàng)目中 src/router.config.json
{
"mode": "history",
"domain": "https://www.chameleon.com",
"routes":[
{
"url": "/helloworld",
"path": "/pages/HelloWorld/HelloWorld",
"name": "helloworld",
"mock": "index.php"
}
]
}
其中:
url字段 對(duì)應(yīng) vue 中的path字段;
path字段對(duì)應(yīng) vue 中 import Comp from '/path/to/Comp'中的組件路徑
chameleon 會(huì)自動(dòng)引入 component 字段配置的組件,不需要再配置 component 字段;
總結(jié)
1 注意 CML 項(xiàng)目中不支持路由嵌套,如果有路由嵌套的情況需要考慮轉(zhuǎn)化成組件去實(shí)現(xiàn)
2 在遷移路由的時(shí)候,要一個(gè)一個(gè)路由對(duì)應(yīng)著去遷移
3 vue 項(xiàng)目中的一級(jí)路由的組件都通過(guò) cml init page 去初始化這個(gè)組件
假如 Weex 項(xiàng)目中 src/components/HelloWorld.vue組件內(nèi)有個(gè)子組件 comp;
首先我們修改下這兩個(gè)組件,使其有一些簡(jiǎn)單的新增 todolist 的功能
HelloWorld.vue
<template>
<div class="demo-com">
<div class="title">this is helloworld</div>
<comp @parentClick="handleParentClick"></comp>
</div>
</template>
<script>
import lodash from 'lodash';
import comp from './comp.vue';
export default {
name: 'HelloWorld',
data() {
return {};
},
methods: {
handleParentClick(...args) {
console.log('parentClick', ...args);
},
},
components: {
comp,
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.demo-com {
display: flex;
flex-direction: column;
align-items: center;
height: 400px;
justify-content: center;
}
.title {
align-self: center;
color: #61c7fc;
font-size: 72px;
margin-bottom: 20px;
}
</style>
注意:如果第三方倉(cāng)庫(kù)中的某些 API 依賴該平臺(tái)的全局變量,那么這些 API 只能在該平臺(tái)使用,在其他平臺(tái)是無(wú)效的;
comp.vue
<template>
<div>
<input type="text" v-model="todo" />
<div v-for="(item, index) in todos">
{{ item }}
</div>
<div @click="addTodo">addTodo</div>
<div @click="handleClick">觸發(fā)父組件事件</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data() {
return {
todo: 'todo1',
todos: [],
};
},
methods: {
addTodo() {
this.todos.push(this.todo);
},
handleClick() {
console.log('click');
this.$emit('parentClick', {
value: 1,
});
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped></style>
cml init page
輸入 HelloWorld
利用命令行命令,在src/pages中生成對(duì)應(yīng)的頁(yè)面
<template>
<view><text>HelloCML</text></view>
</template>
<script>
class HelloWorld {
//...
}
export default new HelloWorld();
</script>
<style></style>
<script cml-type="json">
{
"base": {
"usingComponents": {}
},
"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 init component
選擇 Normal component
輸入 comp
生成的組件如下
<template>
<view><text>HelloCML</text></view>
</template>
<script>
class Comp {
//...
}
export default new Comp();
</script>
<style></style>
<script cml-type="json">
{
"base": {
"usingComponents": {}
}
}
</script>
假設(shè) Weex 項(xiàng)目src/components/HelloWorld.vue中引用了其他組件 import comp from './comp.vue';
對(duì)應(yīng)到 CML 項(xiàng)目 組件需要在 usingComponents 引用,不需要在配置 components字段
修改src/pages/HelloWorld/HelloWorld.cml 頁(yè)面配置,如下:
<script cml-type="json">
{
"base": {
"usingComponents": {
"comp":"/components/comp/comp"
}
}
}
</script>
總結(jié):
1 router.js中對(duì)應(yīng)的組件需要通過(guò) cml init page生成,然后在 router.config.js中配置對(duì)應(yīng)路由
2 組件內(nèi)部引用的子組件要通過(guò)cml init component生成,然后通過(guò) usingComponents字段去引用
3 組件內(nèi)引用的其他 js 庫(kù),比如import lodash from 'lodash'仍然通過(guò)import的形式引用
這里以 CML 的 Vue 語(yǔ)法
假設(shè),原有 vue 項(xiàng)目代碼,如下:
<div class="scroller-wrap">
數(shù)據(jù)綁定
<div>{{}}</div>
條件渲染
<div v-if="condition1">v-if</div>
<div v-else-if="condition2">v-else-if</div>
<div v-else>v-else</div>
循環(huán)
<div v-for="(item ,index) in array"></div>
事件綁定
<div id="tapTest" @click="handleClick">Click me!</div>
</div>
那么,使用 CML 的類 Vue 語(yǔ)法后:整體基本上不用變,只需要將標(biāo)簽改成 CML 的內(nèi)置標(biāo)簽即可。
<view class="scroller-wrap">
數(shù)據(jù)綁定
<view>{{}}</view>
條件渲染
<view v-if="condition">v-if</view>
<view v-else-if="condition1">v-else-if</view>
<view v-else>v-else</view>
循環(huán)
<view v-for="(item ,index) in array"></view>
事件綁定
<view id="tapTest" @click="handleClick">Click me!</view>
</view>
以下表格列出 Weex 的內(nèi)置組件遷移到 CML 項(xiàng)目中的對(duì)應(yīng)情況,不能在視圖層用 Weex 端特有的組件,需要通過(guò)以下標(biāo)簽進(jìn)行替換
除非是通過(guò)多態(tài)組件調(diào)用的下層組件才可以使用。
對(duì)于 Weex 內(nèi)置的組件,CML 提供了大部分與之對(duì)應(yīng)的可以跨端的組件。
Weex 內(nèi)置組件 | CML | 備注 |
---|---|---|
<div> | <view> | 支持跨多端 |
<text> | <text> | 支持跨多端 |
<image> | <image> | 支持跨多端 |
<list> | <list> | 支持跨多端 |
<cell> | <cell> | 支持跨多端 |
<loading> | <c-loading> | 支持跨多端 |
<scroller> | <scroller> | 支持跨多端 |
<slider> | <carousel> | 對(duì)于輪播圖組件,chameleon 內(nèi)置了carousel 組件,如果想要用原生的slider ,需要在多態(tài)組件中通過(guò) origin-slider 使用 |
<textarea> | <textarea> | 支持跨多端 |
<input> | <input> | 支持跨多端 |
<video> | <video> | 支持跨多端 |
chameleon 不支持的 Weex 內(nèi)置組件
Weex 內(nèi)置組件 | 在 CML 中的替換方式 |
---|---|
<a> | 可以通過(guò)給一個(gè) text 標(biāo)簽綁定事件,通過(guò) chameleon-api 提供的接口打開頁(yè)面 |
<waterfall> | 該組件不支持跨多端,僅可在多態(tài)組件中使用 |
<web> | 該組件不支持跨端,僅可在多態(tài)組件中使用 |
<richtext> | 該組件不支持跨端,僅可在多態(tài)組件中使用 |
根據(jù)以上教程,我們可以遷移HelloWorld.vue和comp.vue中的模板內(nèi)容了
HelloWorld.cml
<template lang="vue">
<view>
<text>this is helloworld</text>
<comp @parentClick="handleParentClick"></comp>
</view>
</template>
comp.cml
<template lang='vue'>
<view>
<input type="text" v-model="todo" ></input>
<div v-for="(item,index) in todos">
{{item}}
</div>
<div @click="addTodo">addTodo</div>
<view @click="handleClick"><text>觸發(fā)父組件事件</text></view>
</view>
</template>
API 遷移包括 http 請(qǐng)求 路由跳轉(zhuǎn) 本地存儲(chǔ)等
不能在邏輯層用 Weex 端特有的內(nèi)置模塊,需要通過(guò)以下chameleon-api提供的進(jìn)行替換
除非是通過(guò)多態(tài)組件調(diào)用的下層組件才可以直接使用。
Weex | CML | 備注 |
---|---|---|
animation | chameleon-api 中的 createAnimation | 參考 |
cliboard | chameleon-api 中的 clipBoard | 參考 |
dom | chameleon-api 中的 getRect | 參考 |
globalEvent | 暫不支持 | |
meta | chameleon-api 中的 getSystemInfo | 參考:可以通過(guò)這個(gè) API 獲取到視口的值然后給頁(yè)面寬高賦值 |
modal | chameleon-api 中的 showToast | 參考 |
navigator | chameleon-api 中的 路由導(dǎo)航 | 參考 |
picker | 擴(kuò)展組件中的 c-picker | 參考 |
storage | chameleon-api 中的數(shù)據(jù)存儲(chǔ) | 參考 |
stream | chameleon-api 中的網(wǎng)絡(luò)請(qǐng)求 | 參考 |
webview | 暫不支持 | |
websockets | chameleon-api 中的 websockets | 參考 |
vue 項(xiàng)目 | cml |
---|---|
this.$emit(xxx,xxx) | this.$cmlEmit(xxx,xxx) |
CML 對(duì) web native wx 各個(gè)端的事件對(duì)象進(jìn)行了統(tǒng)一代理參考。
對(duì)于灰度區(qū)組件(多態(tài)組件)各個(gè)端的事件對(duì)象還是對(duì)應(yīng)端的事件對(duì)象,CML 框架不會(huì)對(duì)灰度區(qū)origin-開頭的標(biāo)簽和第三方組件標(biāo)簽上綁定的事件進(jìn)行事件代理
CML 支持的類 Vue 語(yǔ)法,只有在文檔中列出的語(yǔ)法才支持多端,其他沒有列出的語(yǔ)法僅可以在 Web 端使用,跨端沒有支持,比如 v-html class 的對(duì)象語(yǔ)法 數(shù)組語(yǔ)法等。
longpress appear disappear 事件暫不支持;
chameleon 生成的 Weex 項(xiàng)目默認(rèn)都是開啟了支持事件冒泡的機(jī)制
同時(shí)擴(kuò)展了阻止事件冒泡的語(yǔ)法;
vue 語(yǔ)法(僅僅支持 .stop)
<view @click.stop="handleClick"></view>
cml 語(yǔ)法
<view c-catch:click="handleClick"></view>
總結(jié)
1 由于 CML 是跨多端的框架,所以在 Weex 端特有的環(huán)境變量,比如weex.config等在 CML 中是不支持的
2 對(duì)于 Weex 的內(nèi)置模塊,比如 animation 等,在 chameleon-api 中基本上都有對(duì)應(yīng),參考上文 Weex 內(nèi)置模塊的遷移
根據(jù)以上教程,我們可以遷移HelloWorld.vue和comp.vue中的 js 內(nèi)容了
HelloWorld.cml
<template lang="vue">
<view>
<text>this is helloworld</text>
<comp @parentClick="handleParentClick"></comp>
</view>
</template>
<script>
import lodash from 'lodash';
class HelloWorld {
methods = {
handleParentClick(...args) {
console.log('parentClick', ...args);
},
};
}
export default new HelloWorld();
</script>
comp.cml
<script>
class Comp {
data = {
todo: 'todo1',
todos: [],
};
methods = {
addTodo() {
this.todos.push(this.todo);
},
handleClick() {
this.$cmlEmit('parentClick', {
value: 1,
});
},
};
}
export default new Comp();
</script>
使用 flexbox進(jìn)行樣式布局
關(guān)于樣式的使用教程
模板上的樣式語(yǔ)法
Vue 樣式語(yǔ)法規(guī)范
如果樣式想要適配多端,需要將單位改成cpx;
根據(jù)以上教程,我們可以遷移HelloWorld.vue和comp.vue中的 js 內(nèi)容了
HelloWorld.cml
.demo-com { display: flex; flex-direction: column; align-items: center; height:400cpx;
justify-content: center; } .title { align-self: center; color: #61c7fc; font-size: 72cpx;
margin-bottom: 20cpx; }
更多建議: