邏輯層

2020-05-14 14:20 更新

邏輯層負(fù)責(zé)反饋用戶對(duì)界面操作的處理中心。

邏輯層是終端開發(fā)的“靈魂”。

而 VM 對(duì)象 是邏輯層規(guī)范的輸入口

VM 對(duì)象

字段名類型說(shuō)明
propsObject聲明當(dāng)前組件可接收數(shù)據(jù)屬性
props = { type, default }
type為數(shù)據(jù)類型,default為數(shù)據(jù)默認(rèn)值
dataObjectCML模板可直接使用的響應(yīng)數(shù)據(jù),是連接視圖層的樞紐
methodsObject處理業(yè)務(wù)邏輯與交互邏輯的方法
watchObject偵聽屬性,監(jiān)聽數(shù)據(jù)的變化,觸發(fā)相應(yīng)操作
computedObjectCML模板可直接使用的計(jì)算屬性數(shù)據(jù),也是連接視圖層的樞紐
beforeCreateFunction例初始化之后,數(shù)據(jù)和方法掛在到實(shí)例之前 一個(gè)頁(yè)面只會(huì)返回一次
createdFunction數(shù)據(jù)及方法掛載完成
beforeMountFunction開始掛載已經(jīng)編譯完成的cml到對(duì)應(yīng)的節(jié)點(diǎn)時(shí)
mountedFunctioncml模板編譯完成,且渲染到dom中完成
beforeDestroyFunction實(shí)例銷毀之前
destroyedFunction實(shí)例銷毀后

響應(yīng)式數(shù)據(jù)綁定系統(tǒng)

響應(yīng)式數(shù)據(jù)綁定意味著開發(fā)者只需關(guān)心邏輯處理,通過(guò)數(shù)據(jù)綁定的形式,當(dāng)數(shù)據(jù)變化時(shí)視圖自動(dòng)更新。

通過(guò)這個(gè)簡(jiǎn)單的例子來(lái)看:

<template>
  <view>
    <text>Hello {{ name }}!</text>
    <button c-bind:onclick="changeName">Click me!</button>
  </view>
</template>
<script>
class Index {
  data = {
    name: 'Chameleon',
  };
  methods = {
    changeName: function(e) {
      // sent data change to view
      this.name = 'CML';
    },
  };
}
export default new Index();
</script>

框架首先將邏輯層數(shù)據(jù)中的 name 與視圖層的 name 進(jìn)行了綁定,所以打開頁(yè)面的時(shí)候會(huì)顯示 HelloCML; 當(dāng)點(diǎn)擊按鈕的時(shí)候,視圖層會(huì)發(fā)送 changeName 的事件給邏輯層,邏輯層找到并執(zhí)行對(duì)應(yīng)的事件處理函數(shù); 回調(diào)函數(shù)觸發(fā)后,邏輯層執(zhí)行數(shù)據(jù)賦值的操作,將 data 中的 name 從 CML 變?yōu)?CML,因?yàn)樵摂?shù)據(jù)和視圖層已經(jīng)綁定了,從而視圖層會(huì)自動(dòng)改變?yōu)?Hello CML!。

生命周期

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

chameleon 為組件和 頁(yè)面 提供了一系列生命周期事件,保障應(yīng)用有序執(zhí)行。 如果你想使用某個(gè)端特定的生命周期,請(qǐng)從業(yè)務(wù)出發(fā)使用多態(tài)接口接收特定的生命周期事件回調(diào)。

鉤子執(zhí)行時(shí)機(jī)詳細(xì)
beforeCreate實(shí)例初始化之后,數(shù)據(jù)和方法掛在到實(shí)例之前頁(yè)面會(huì)在該生命周期中返回傳入當(dāng)前頁(yè)面的參數(shù)對(duì)象
created數(shù)據(jù)及方法掛載完成頁(yè)面會(huì)在該生命周期中返回傳入當(dāng)前頁(yè)面的參數(shù)對(duì)象
beforeMount開始掛載已經(jīng)編譯完成的cml到對(duì)應(yīng)的節(jié)點(diǎn)時(shí)在頁(yè)面會(huì)在該生命周期中返回傳入當(dāng)前頁(yè)面的參數(shù)對(duì)象
mountedcml模板編譯完成,且渲染到dom中完成
beforeDestroy實(shí)例銷毀之前
destroyed實(shí)例銷毀后

頁(yè)面 Page 獨(dú)有生命周期

onShow()

chameleon-runtime@0.2.0 開始支持

頁(yè)面顯示/切入前臺(tái)時(shí)觸發(fā)

onHide()

chameleon-runtime@0.2.0 開始支持

頁(yè)面隱藏/切入后臺(tái)時(shí)觸發(fā)

** 注意:頁(yè)面不會(huì)在 onShow、onHide 回調(diào)函數(shù)中返回頁(yè)面參數(shù) **

生命周期回調(diào)函數(shù)

beforeCreate(Object res)

參數(shù)說(shuō)明

名稱類型說(shuō)明
resObject僅有頁(yè)面在該生命周期回調(diào)函數(shù)中會(huì)
返回對(duì)象res:
res = { query } query 是打開當(dāng)前頁(yè)面路徑中的參數(shù)

created(Object res)

參數(shù)說(shuō)明

名稱類型說(shuō)明
resObject僅有頁(yè)面在該生命周期回調(diào)函數(shù)中會(huì)
返回對(duì)象res:
res = { query } query 是打開當(dāng)前頁(yè)面路徑中的參數(shù)

beforeMount(Object res)

參數(shù)說(shuō)明

名稱類型說(shuō)明
resObject僅有頁(yè)面在該生命周期回調(diào)函數(shù)中會(huì)
返回對(duì)象res:
res = { query } query 是打開當(dāng)前頁(yè)面路徑中的參數(shù)

鉤子示例

<template>
  <view> </view>
</template>
<script>
class Index {
  beforeCreate(query) {
    // data數(shù)據(jù)掛載到this根節(jié)點(diǎn)上之前,以及methods所有方法掛載到實(shí)例根節(jié)點(diǎn)之前
    // 注意:只用頁(yè)面的 beforeCreate鉤子 會(huì)返回頁(yè)面query
    console.log('App beforeCreate: 打開當(dāng)前頁(yè)面路徑中的參數(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>

生命周期多態(tài)

CML 在 *.[web|weex|wx].cml 文件中支持生命周期的多態(tài),可以針對(duì)不同的平臺(tái)添加專屬鉤子函數(shù)。

假設(shè)有一個(gè)頁(yè)面home.cml,需要使用小程序頁(yè)面分享生命周期微信端 onShareAppMessage,可以如下實(shí)現(xiàn):

  1. 項(xiàng)目根目錄執(zhí)行 cml init component,選擇 multimode-interface 多態(tài)接口,輸入 interface name: lifecycleInterface,自動(dòng)生成src/components/lifecycleInterface 
  2. 在src/components/lifecycleInterface/lifecycleInterface.cml多態(tài)接口中,添加如下代碼:
<script cml-type="interface">
interface LifecycleInterfaceInterface {
  onShareAppMessage(): void;
}
</script>

<script cml-type="web">
class Method implements LifecycleInterfaceInterface {
  onShareAppMessage() {
    console.log('web share');
  }
}
export default new Method();
</script>

<script cml-type="weex">
class Method implements LifecycleInterfaceInterface {
  onShareAppMessage() {
    console.log('weex share');
  }
}
export default new Method();
</script>

<script cml-type="wx">
class Method implements LifecycleInterfaceInterface {
  onShareAppMessage() {
    console.log('wx share');
  }
}
export default new Method();
</script>

<script cml-type="alipay">
class Method implements LifecycleInterfaceInterface {
  onShareAppMessage() {
    console.log('alipay share');
  }
}
export default new Method();
</script>

<script cml-type="baidu">
class Method implements LifecycleInterfaceInterface {
  onShareAppMessage() {
    console.log('baidu share');
  }
}
export default new Method();
</script>
  1. 在 home.cml 文件,使methods合并lifecycleInterface多態(tài)方法
<template>
  <view>
    <text>home頁(yè)面</text>
  <view>
</template>
<script>
import lifecycleInterface from '../../components/lifecycleInterface/lifecycleInterface'
  class Home {
    data = {}
    computed = {}
    watch = {}
    methods = {
      ...lifecycleInterface
    }
    beforeCreate(res) {}
    created() {}
  }
  export default new Home()
</script>

計(jì)算屬性 computed

對(duì)于模板內(nèi)任何復(fù)雜邏輯,你都應(yīng)當(dāng)使用計(jì)算屬性

示例

<template>
  <view>
    <text>Original message: "{{ message }}"</text>
    <text>Computed reversed message: "{{ reversedMessage }}"</text>
  </view>
</template>
<script>
class Index {
  data = {
    message: 'Hello',
  };
  computed = {
    // 計(jì)算屬性的 getter
    reversedMessage: function() {
      return this.message
        .split('')
        .reverse()
        .join('');
    },
  };
}
export default new Index();
</script>

結(jié)果:

Original message: "Hello"

Computed reversed message: "olleH"

這里我們聲明了一個(gè)計(jì)算屬性 reversedMessage。 我們提供的函數(shù)將用作屬性 reversedMessage 的 getter 函數(shù),當(dāng) message 發(fā)生改變時(shí),reversedMessage 也會(huì)更新

偵聽屬性 watch

提供了一種更通用的方式來(lái)觀察和響應(yīng)實(shí)例上的數(shù)據(jù)變動(dòng)

示例

<template>
  <view>
    <text>fullName is : "{{ fullName }}"</text>
  </view>
</template>
<script>
class Index {
  data = {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar',
  };
  watch = {
    firstName: function(newV, oldV) {
      this.fullName = newV + ' ' + this.lastName;
    },
    lastName: function(newV, oldV) {
      this.fullName = this.firstName + ' ' + newV;
    },
  };
}
export default new Index();
</script>

除了 watch 選項(xiàng)之外,你還可以使用命令式的 this.$watch API。

但是,上面代碼是命令式且重復(fù)的。將它與計(jì)算屬性的版本進(jìn)行比較:

<script>
class Index {
  data = {
    firstName: 'Foo',
    lastName: 'Bar',
  };
  computed = {
    fullName: function() {
      return this.firstName + ' ' + this.lastName;
    },
  };
}
</script>

所以,不要濫用 watch ~

API

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

代碼示例

import cml from 'chameleon-api';
cml.showToast({
  message: 'Hello world!',
  duration: 1000,
});

通常,在 CML API 有以下幾種類型:

通用 API

大多數(shù) API 都是異步 API,如 cml.get 等。這類 API 接口通常都接受一個(gè) Object 類型的參數(shù),返回 Promise ,對(duì)應(yīng)請(qǐng)求成功和失敗回調(diào),支持 then 鏈?zhǔn)秸{(diào)用。

代碼示例

cml
  .get({
    url: 'https://cml.com/api/user/1',
  })
  .then(
    (res) => {
      cml.showToast({
        message: JSON.stringify(res),
        duration: 2000,
      });
    },
    (err) => {
      cml.showToast({
        message: JSON.stringify(err),
        duration: 2000,
      });
    },
  );

運(yùn)行時(shí)相關(guān) API

代碼示例

import a from 'a.js';

export { a };

數(shù)據(jù)管理 Store API

代碼示例

// store.js
import createStore from 'chameleon-store';

const store = createStore({ state, mutations, actions, getters, modules });

export default store;


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

掃描二維碼

下載編程獅App

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

編程獅公眾號(hào)