Product | technology drops

The author | Xu Guodong



Introduction: With all kinds of small procedures bloom, the business of cross-terminal demand more and more obvious. Although the environment at each end is constantly changing, no matter all kinds of applets, Weex, React-Native, Flutter and fast applications, they are always the same is the DESIGN idea of THE MVVM architecture. Today, we bring you Chameleon migration guide, a set of code to complete the requirements of each side, full of dry goods ~

CML, as a framework for truly allowing a set of code to run multi-terminal, provides a standard MVVM mode for unified development of various terminals. At the same time, it has independent runtime framework (Runtime), data management (Store), component library (UI), interface (API). In addition, CML has done a lot of work in strengthening cross-end capabilities, unifying capabilities, and performing consistently.

Today, in order to make your project elegant upgrade, fast access, bring you a sumptuous CML migration guide.

Video tutorial source address: github.com/jalonjs/cml…

Address: video tutorial sfwb.didistatic.com/static/wb/5…




Reading Index

  • The directory structure

  • How to Modify the Configuration

  • How do I use routing capabilities

  • How to sign up

  • How do I declare the life cycle

  • How does the data respond to the view

  • Event interaction

  • Layout and Appearance

  • Custom Components

  • How to implement parent-child component event communication

  • Component Usage Summary

  • How to invoke platform interface capabilities

  • Migrating instance



Directory Structure

Like wechat applets, CML consists of an APP that describes the overall program and multiple pages that describe their respective pages.

Small program directory structure

1. 2├─ Components 3├─ pages 4├─ app.js 5├─ app.js 6├─ app.json 7├─ App.wxss // Global style 8 ├ ─ project.config.json // project config fileCopy the code

CML directory structure

│ ├── ├─ web │ ├─ weex 8│ ├─ config.json │ ├─ web │ ├── ├─ web │ ├─ weex 8│ └ 9 │ ├── Node_modules 10 │ ├── Mock │ ├── SRC // Source Code Development directory 12│ ├── app │ ├── Assets 14 │ ├ ─ ─ the components / / contains components 15 │ ├ ─ ─ pages / / contains page 16 │ ├ ─ ─ store / / data management 17 │ └ ─ ─ the router. The config. The json / / routing configuration file 18 ├ ─ ─ Chameleon. Config. Js / / project configuration file 19 └ ─ ─ package. The json / / NPM package configuration fileCopy the code

How to modify the configuration

In the small program project, divided into:

Small procedures – project configuration

The project can be configured using the project.config.json file in the project root directory.

Configuration example:

1{
2  "miniprogramRoot": "./src",
3  "debugOptions": {}
4}
Copy the code

Small procedures – global configuration

The app.json file in the root directory of the applets is used for global configuration of wechat applets, determining the path of page files, window performance, setting network timeout, setting multiple tabs, etc

Configuration example:

1 {2"pages": ["pages/index/index"."pages/logs/index"],
 3  "window": {4"navigationBarTitleText": "Demo"5}, 6"networkTimeout": {7"request": 8, 10000"downloadFile": 10000 9} 10}Copy the code

Small procedures – page configuration

Each applet page can also use a.json file to configure the window appearance of the page.

The configuration of the page can only set part of the window configuration items in app.json. The configuration items in the page overwrite the same configuration items in the window of app.json.

Configuration example:

1{
2  "navigationBarBackgroundColor": "#ffffff",
3  "navigationBarTextStyle": "black"4,"navigationBarTitleText": "Wechat Interface Function Demonstration"May,"backgroundColor": "#eeeeee"6,"backgroundTextStyle": "light"
7}
Copy the code

Similarly, CML projects are divided into the following configuration schemes:

CML – project configuration

Chameleon.config. js is a configuration file for your project that you can customize to build, such as hash, compression, etc.

Configuration example:

1 // Set the online path of the static resource 2 const publicPath ='//www.static.chameleon.com/static'; 3 // Set API request prefix 4 const apiPrefix ='https://api.chameleon.com'; Merge ({7 wx: {8 build: {apiPrefix} 9}, 10 Alipay: {11 build: {apiPrefix} 12}, 13 Baidu: { 14 build: {apiPrefix} 15 }, 16 web: { 17 dev: { 18 hot:true,
19      console: true
20    },
21    build: {
22      publicPath: `${publicPath}/web`,
23      apiPrefix
24    }
25  },
26  weex: {
27    build: {
28      publicPath: `${publicPath}/weex`,
29      apiPrefix
30    }
31  }
32})
Copy the code

CML – Global setting

The of the app. CML file in the APP directory of the CML project is used to configure CML applications globally, with cross-end configuration and differentiation capabilities.

Configuration example:

 1<script cml-type="json">
 2{
 3  "base": {4"window": {5"navigationBarTitleText": "All ends share title", 6}, 7"permission": {8"scope.userLocation": {9"desc": "Your location information will be used to display the effects of the applet location interface."10} 11} 12}, 13"wx": {14"window": {15"backgroundTextStyle":"light",
16      "navigationBarBackgroundColor": "#fff",
17      "navigationBarTitleText": "Differentiated title"18,"navigationBarTextStyle":"black"19} 20}, 21"baidu": {22"window"23: {"backgroundTextStyle": "light"24} 25}, 26"alipay": {27"window": {28"defaultTitle": "Chameleon"
29      }
30  }
31}
32</script>
Copy the code

CML – Page/component configuration

The referenced component is registered through the usingComponents configuration path.

Configuration example:

 1  <script cml-type="json"> {2 3"base": {4"usingComponents": {5"navi": "/components/navi/navi"6,"navi-npm": "cml-test-ui/navi/navi"7} 8}, 9"wx": {10}, 11"alipay": {12}, 13"baidu": {14}, 15"web": {16}, 17"weex": {
18  }
19}
20</script>
Copy the code

How to use routing capabilities

Small procedures configuration routing

The Pages field in the app.json configuration item list is used to specify which pages the applet consists of, and each item corresponds to the path + file name information of a page.

The first entry in the array represents the initial page (home page) of the applet. To add/subtract pages, modify the Pages array.

If the project has pages/index/index.wxml and pages/logs/logs. WXML, it needs to be written in app.json.

1{
2  "pages": ["pages/index/index"."pages/logs/logs"]
3}
Copy the code

CML configuration routing

SRC /router.config.json is a route configuration file. CML has a set of built-in route management modes for all ends. The corresponding CML route configuration mapping is as follows:

1 {2"mode": "history",
 3  "domain": "https://www.chameleon.com"4,"routes": [{5 6"url": "/cml/h5/index"7,"path": "/pages/index/index"8,"mock": "index.php"9}, 10 {11"url": "/cml/h5/logs",
12      "path": "pages/logs/logs"13,"mock": "logs.php"14} 15] 16}Copy the code

File names do not need to be suffixed, and the CML framework will automatically find.cML files for processing.

Small procedures use routing

  • Open a new page: call API wx.navigateTo

  • Page redirection: Call API wx.redirectTo

  • NavigateBack: call API wx.navigateBack

  • Open another small program: call API Wx. navigateToMiniProgram

  • Return to a small program: call API wx. NavigateBackMiniProgram

CML uses routing

Adaptively open the same route PATH in different environments according to the uniform resource index URI:

  • Open a new page: call chameleon-api cmL. navigateTo

  • Page redirection: Call chameleon-API cmL.redirectto

  • NavigateBack: call chameleon-api cmL. navigateBack

  • Open another cross-application: call chameleon-api cmL.open

  • Go back to the previous cross-application: call chameleon-api cmL.close

How to Register

Small procedures registration application

In the applet project, the App() function is used to register a applet. Accepts an Object parameter that specifies the life cycle callback of the applet, etc.

Sample code:

1 App({
2  onLaunch(options) {
3    // Do something initial when launch.
4  },
5  globalData: 'I am global data'
6})
Copy the code

CML registration application

Sample code:

 1 <script>
 2 import store from '.. /store/index.js'
 3 import routerConfig from '.. /router.config.json';
 4
 5 class App {
 6  data = {
 7    store,
 8    routerConfig
 9  }
10  created(res) {
11  }
12 }
13
14 export default new App();
15 </script>
Copy the code

Json app.js app.wxss SRC /app/app.cml



Small procedures registration page

In applets, the Page(Object) function is used to register a Page. Accepts an Object parameter that specifies the page’s initial data, lifecycle callbacks, event handlers, and so on.

Sample code:

 1 // index.js
 2 Page({
 3  data: {
 4    text: 'This is page data.'
 5  },
 6  changeText: function(e) {
 7    // sent data change to view
 8    this.setData({
 9      text: 'CML'10}) 11} 12})Copy the code

CML Registration page

Sample code:

 1 <script>
 2 class Index {
 3  data = {
 4    text: 'Chameleon'
 5  }
 6  methods = {
 7    changeText: function(e) {
 8      // sent data change to view
 9      this.text = 'CML';
10    }
11  }
12  computed = {}
13  watch = {}
14 };
15 export default new Index();
16 </script>
Copy the code

Small procedures registration components

In the applets project,

The Component(Object) constructor is used to define components, specifying their properties, data, methods, and so on when called.

Sample code:

1 Component({2 properties: {3 myProperty: {//type: String, // Type (mandatory) 5 value:' '(Optional) 6}, 7 myProperty2: String 8}, 9 data: {10 text:' '}, // private data that can be used for template rendering 12 13 // Lifecycle functions that can be functions, or a method name defined in the methods section 14attached() {}, 15ready() { },
16  methods: {
17    onMyButtonTap() {18 this.setData({19 // Update attributes and data in a similar way to update page data 20 text:'wx'21}) 22} 23} 24})Copy the code

CML registered components

Sample code:

1 <script> 2 class MyComponent {3 props = {4 myProperty: {//typeString, // Type (mandatory) 6 default:' '7}, 8 myProperty2: String 9} 10 data = {11 text:' '} // Private data that can be used for template rendering 13 14beforeMount15 () {}mounted() {}
16  methods = {
17    onMyButtonTap() {
18      this.text = 'cml'
19    }
20  }
21  computed = {}
22  watch = {}
23 };
24 export default new MyComponent();
25 </script>
Copy the code

How to declare the life cycle

Unifying the definition of application life cycle is an important component of cross-end framework and the only way to migrate.

Small procedures statement life cycle

You can pass the Object argument to App(Object), Page(Object), Component(Object), which specifies the life cycle callback of the applet, etc.

Code examples:

 1 // index.js
 2 Page({
 3  onLoad(options) {
 4    // Do some initialize when page load.
 5  },
 6  onReady() {
 7    // Do something when page ready.
 8  },
 9  onShow() {
10    // Do something when page show.
11  },
12  onHide() {
13    // Do something when page hide.
14  },
15  onUnload() {
16    // Do something when page close.
17  },
18  onShareAppMessage() {/ / 19return custom share data when user share.
20  }
21})
Copy the code

CML statement life cycle

An instance of an object returned in the.cML file code block that specifies the lifecycle callback.

Sample code:

1 <script> 2 class Index {3 beforeCreate(query) {4 <script> 2 class Index {3 beforeCreate(query) {4 Just using the page's beforeCreate hook will return the page query 6 console.log('App beforeCreate: Opens the current page path with the parameter is', query)
 7  }
 8  created() {9 // Events in data,methods complete 10 console.log()'App created'12) 11}beforeMount14 console.log() {13 // start mounting the compiled CML to the corresponding node'App beforeMount'15} (16)mounted() {17 // The CML template is compiled and rendered into the DOM, and only executed once in its lifetime. 18 console.log()'App mounted'19} 20)beforeDestroy() {21 // before instance destruction 22 console.log()'App beforeDestroy'23} 24)destroyed() {25 // After instance destruction 26 console.log()'App destroyed') 27} 28}; 29export default new Index();
30 </script>
Copy the code

App life cycle mapping

Small programapp.jsLife cycle in -> CMLsrc/app/app.cml

Page Life cycle mapping

In the life cycle of small programs Page () – > CML SRC/pages/mypage/mypage. CML

  1. Small program chameleon
  2. onLoad                                                           beforeCreate

  3. onShow                                                          mounted

  4. onUnload                                                       destroyed

  5. OnReady life cycle polymorphism
  6. OnHide life cycle polymorphism
  7. OnShareAppMessage lifecycle polymorphism

Component Lifecycle Mapping

Small application Component () – > in the life cycle of CML SRC/components/mycomponent/mycomponent CML



Life cycle summary

Each CML instance (App, Page, Component) goes through a series of initialization procedures when it is created.

For example, you need to set up data listening, compile templates, mount instances to CML nodes and update CML nodes when data changes, and so on. There are also functions called lifecycle hooks that run along the way, giving developers the opportunity to add their own code at different stages.

CML provides a series of life cycle events for apps, pages, and components to ensure orderly application execution.

Alternatively, if you want to use an end-specific lifecycle, you can use lifecycle polymorphism from a business perspective.

How does data respond to views

Today, two-way data binding and one-way data flow are common to developers, and THE MVMM development model is standard in the framework.

How are data binding, conditional rendering, and list rendering written?

Sample code:

Small procedures use data response



CML use data response

1 <template> 2 <! --index.cml--> 3 <view class="scroller-wrap"4 > <! <view>{{message}}</view> 6 <! --> 7 <view c-if="{{view == 'WEBVIEW'}}">WEBVIEW</view>
 8  <view c-else-if="{{view == 'APP'}}">APP</view>
 9  <view c-else="{{view == 'MINA'}}">MINA</view> 10 <! --> 11 <view c-for="{{array}}" c-for-index="index" c-for-item="item">{{item}}</view>
12 </view>
13 </template>
14 <script>
15 class Index {
16  data =  {
17    message: 'Hello MINA! ',
18    view: 'MINA',
19    array: [1, 2, 3, 4, 5]
20  }
21
22  beforeCreate () {
23    this.message = 'cml'24}}; 26export default new Index();
27 </script>
Copy the code

Data response summary

The CML runtime framework provides a cross-end responsive Data binding system. When Data is modified, only the Data needs to be modified in the logical layer, and the view layer will make corresponding updates.

Just need to view<–>model interaction part of the logic, simple migration, can make it become a multi-terminal data response system.

Event Interaction

CML supports some basic events to ensure that all side effects (types, bindings, event objects) run consistently.

Sample code:

Small program use events

1 <! --wxml--> 2<view id="tapTest" data-hi="WeChat" bindtap="tapName">Click me! </view>Copy the code

1// page.js
2Page({
3  tapName(event) {
4    console.log(event)
5  }
6})
Copy the code

CML use events

 1 <template>
 2  <view id="tapTest" data-hi="WeChat" c-bind:tap="tapName"> 3 <text>Click me! </text> 4 </view> 5 </template> 6 <script> 7 class Index {8 methods = {9 tapName(e) {10 // Print event object 11 console.log('Event object :', e); 12} 13} 14} 15export default new Index();
16 </script>
Copy the code

Summary of the use of events

Custom events are also supported for communication between parent and child components.

In addition, CML does not limit your freedom if you want to use end-specific events, you can use component polymorphism or interface polymorphism differentiation for business purposes.

Layout and appearance

There are differences in cascading style sheet (CSS) implementations that describe layout and appearance at each end, including but not limited to layout, box models, positioning, and text.

As a result, the CML framework has built-in cross-end consistency base styling capabilities.

Also, a Style specification CMSS(Chameleon Style Sheet) for describing pages is defined.

How to import external style

The @import statement can be used to import an external style sheet, followed by the relative path of the external style sheet to be imported, using; Indicates the end of the statement.

Small procedures into the external style

Sample code:



CML import external style

Detailed documentation

Sample code:



Style use summary

At the same time, in order to unify the multi-end size units and render the same effect, as well as the responsive layout of the page, THE CML project uniformly adopts CPX as the size unit and stipulates that the screen 750px (full screen) visual draft is taken as the standard.

Moreover, each side of the stylesheet has different capabilities and is one of the main areas of project migration.

In addition, CML does not limit your freedom if you want to use end-specific style capabilities, you can use style polymorphism for business purposes

Note: Since chameleon applications are cross-native applets, flexbox must be used for style layout if cross-native is required.

Custom components

Developers can abstract functional modules within a page into custom components that can be reused across different pages. Custom components are very similar to the base components when used.

Small procedures for creating custom components

Code examples:

1 Component({2 properties: {3 // Here we define the innerText property, whose value can be specified by specifying 4 innerText: {5 when used by the Componenttype: String,
 6      value: 'default value'// someData: {} 12}, 13 methods: {14 // here is a custom method 15customMethod() {} 16} 17})Copy the code

CML create custom components

Sample code:

1 <script> 2 class MyComponent {3 props = {4 // Here is the innerText property defined. The value of the innerText property can be specified when the component is usedtype: String,
 7      value: 'default value'// someData: {} 13} 14 methods = {15 // here is a custom method 16customMethod() {}
17  }
18  computed = {}
19  watch = {}
20};
21export default new MyComponent();
22</script>
Copy the code

How to use custom components

Before using a registered custom component, a reference is declared. In this case, you need to provide the label name of each user-defined component and the path to the user-defined component file.

Small programs use custom components

Code examples:

Declare references in page.json

1{
2  "usingComponents": {3"component-tag-name": "path/to/the/custom/component"4} 5}Copy the code

Used in page.wxml

1 <view> 2 <! -- Here is a reference to a custom component --> 3 <component-tag-name inner-text="Some text"></component-tag-name>
4 </view>
Copy the code

CML uses custom components

Code examples:

In page. CML for reference declaration

1<script cml-type="json">
2{
3  "base": {4"usingComponents": {5"component-tag-name": "path/to/the/custom/component"
6      }
7  }
8}
9</script>
Copy the code

is used in page.cml

1<template> 2<view> 3 <! -- Here is a reference to a custom component --> 4 <component-tag-name inner-text="Some text"></component-tag-name>
5</view>
6</template>
Copy the code

How to achieve father-son component event communication

Event system is one of the main ways of communication between components. Custom components can trigger arbitrary events that pages referencing components can listen for.

Small program components communications

Code examples:



CML component communications

Code examples:



Components use summary

Like applets, the CML framework provides a number of built-in components and extension components that smooth out the differences and make it easy for developers to combine these components to create powerful applications.

Extension components need to be brought in extra. Such as:

1<script cml-type="json">
2{
3  "base": {4"usingComponents": {5"c-dialog": "cml-ui/components/c-dialog/c-dialog"
6      }
7  }
8}
9</script>
Copy the code

When CML build build packaging is performed, the CML framework packages referenced built-in components and extension components as needed, slimming down the code.

Both built-in components and extension components are supported across multiple endpoints. For some components that do not provide one end, component polymorphism can be implemented.

If you want to use native components on the applet side, you can prefix the native tag with Origin -* and the CML framework will render the native component reference.

Note: Origin -* can only be used in grayscale files.

If using the native map component

in map.wx. CML:

1 <! -- map.wx.cml --> 2 <template> 3 <origin-map 4 id="map"
 5    longitude="113.324520"
 6    latitude="23.099994"
 7    controls="{{controls}}"
 8    bindcontroltap="controltap"
 9    style="width: 100%; height: 300px;"
10  ></origin-map>
11 </template>
Copy the code

Components how to call platform interface capabilities

In the mini program, you can use wechat’s native API to enable functions such as access to user information, local storage, and payment.

Sample code:

1try {
2  wx.setStorageSync('name'.'Hanks')
3} catch (e) {
4  console.error(e)
5}
Copy the code

Also, in a CML project you can call this:

Sample code:

1import cml from 'chameleon-api'
2cml.setStorage('name'.'Hanks').then((res)=>{
3  console.log(res)
4},function(e){
5  console.error(e)
6})
Copy the code

Use summary excuses

CML framework provides a rich polymorphic interface, which can be used to adjust the native capabilities provided by each end, such as system information, element node information, animation effects, local storage, network requests, geographical location, etc. Please refer to the API documentation.

Chameleon-api provides interfaces that support cross-endpoints. For some native interfaces that are not provided, they can be called through interface polymorphism.

Migration example

The CML guide for migrating each end (VUE, WEEX, and applet) and the specific migration document for exporting CML components to each end are given below:

  • How do I migrate a Vue project to Chameleon

  • How do I migrate a Weex project to Chameleon

  • How to migrate a wechat applets to Chameleon

  • A normal project uses the Chameleon cross-dialog component





Click on the image to learn more:

For installation, usage, and FREQUENTLY asked questions, see the following links:

GitHub:github.com/didi/chamel…

Quick start: cml.js.org/doc/quick_s…


At the same time, welcome to join the “Chameleon User Exchange Group”. Please reply “Chameleom” in the background of didi Technical official account to join


▍ END



                                    

Xu Guodong drops | senior software development engineer

Member of Chameleon, mainly responsible for framework runtime, component ecology and other related development work. Like to specialize in front-end technology and be interested in cutting-edge technology in the field. Students who have cross-related views are welcome to discuss with each other.