目錄
?
組件介紹
組件聲明結構
組件接口
script
dependency
template
style
狀態注入
接口聲明
組件介紹
Component?擴充自?Vue
?的組件, 提供了?Vue
?組件對等的輸入參數能力。在代碼書寫時提供類?class
?的裝飾器?Decorator
?風格。
import { Component, Watch } from '@ali/kylin-framework';
一個組件可以包含數據、JSX 渲染函數、模板、掛載元素、方法、生命周期等?Vue
?的?options
?選項的對等配置。
組件聲明結構
組件聲明包括以下幾部分, 分別使用?@Component
?和?@Watch
?兩種不同裝飾器進行包裝:
- class 類聲明, 使用裝飾器?
@Component
。 - 類成員聲明, 不使用裝飾器。
- 類成員方法聲明, 一般不裝飾器, 除非該方法需要?
watch
?另外一個已聲明的變量。
舉例子
<!-- Hello.vue -->
<template><div>hello {{name}}<Child></Child></div>
</template>
<style>/* put style here */
</style>
<component default="Child" src="./child.vue" />
<script>import { Component } from '@ali/kylin-framework';@Componentclass Hello {data = {name: 'world'}}export default Hello;
</script>
組件接口
跟 vue 基本一致,組件定義寫在?.vue
?文件內,以下是一個簡單的例子:
<template><div><AButton @click="onClick">點擊</AButton></div>
</template>
<style lang="less" rel="stylesheet/less">/* less */
</style>
<dependency component="{ AButton }" src="@alipay/antui-vue" lazy/>
<script type="text/javascript">import { Component } from '@ali/kylin-framework';@Componentexport default class IndexView {props = {}data = {c:666}get comput() { return this.data.c * 2 }onClick() {}mounted() {}}
</script>
上述例子中,有<template>
、<style>
、<script>、<dependency>
?? 4 個頂級標簽
其中?<template>
、?<style>
?與?vue
?中定義一致。下文將對這 4 個標簽的具體作用分別進行闡述。
script
1.class 結構
定義一個 Component ,使用類 class 的裝飾器 Decorator 風格。
其中裝飾器有?@Component
?和?@Watch
?2 種,通過以下方式引入。
import { Component, Watch } from '@ali/kylin-framework';
@Component
export default class Hello {
}
2.方法類型
@Component
組件以 class 形式聲明,必須對該 class 進行裝飾器修飾。
在 class 內部,不需要被手動處理成員變量
,babel
?插件在構建過程中自動進行處理。
而?成員函數
?一般不需要裝飾器掛載,除非是使用?@Watch
?的場景,其中?@Component
?會處理的屬性如下表所示。
成員類型 | 名稱 | 功能 |
---|---|---|
get/set property | * | 用以轉換成?Vue ?的?computed ?計算屬性,可以直接通過?this[varName] ?調用。 |
method | 生命周期 | 生命周期方法,與?Vue ?對等。 |
method | * | 普通成員方法, 用以轉換成?Vue ?的?methods ?方法列表。 |
分別舉例:
getter/setter屬性
@Component
export default class Hello {get computName() {// to sth}
}
上述?getter
?聲明,等價于如下 vue 配置
HelloOption = {computed: {computName: {get: computName() {// to sth}}}
}
同理,setter
?也會被提取,如果同時存在?getter
?和?setter
?則會被一起提取。
生命周期函數
@Component
export default class Hello {created() {}mounted() {}
}
上述?created
?和?mounted
?生命周期函數,會被提取為數組。
TestOption = {created: [function created(){}],mounted: [function mounted(){}],
}
支持的生命周期方法名如下,beforeCreate
、created
、beforeMount
、mounted
、beforeUpdate
、updated
、?beforeDestroy
、destroyed
。
Watch
該裝飾器的出現,只是因為?watch
?需要有以下幾個要素:
- 被監聽的變量名
- 監聽選項
- 觸發函數
用法
完整的?@Watch
?接口如下表所示。
function Watch( key: string [, option: Object = {} ] ): PropertyDecorator
參數名 | 類型 | 用途 | |
---|---|---|---|
key | string | 監聽的參數名,來自?computed 、data 、props 三者之一。 | |
option | deep | boolean | 若監聽的是復雜對象,其內層數據變更是否觸發,默認為?false 。 |
immediate | boolean | 立即以表達式的當前值觸發回調,默認為?false |
示例
- 對于?
@Watch
?裝飾的成員函數,支持對成員函數配置多個變量的監聽,如下同時對?a
?和?c
?的變化進行了監聽,如果任何一個發生變化,會觸發?OnChangeA
?成員方法。 - 如下,
OnChangeA
?本質是成員方法,所以他也會和其他成員方法一起被提取到methods
塊中,那么必須保證沒有與其他方法重名。 - 如果對Watch有額外配置項,請按?
@Watch('a', {deep: false})
的方法傳入。配置項請參考?watch配置項。
@Component
class WTest {data = {a: {b: 2},c: 3}@Watch('c')@Watch('a', {deep: true}) OnChangeA(newVal, oldVal) {}
}
注意: 以上對?data.a
?的監聽,會轉換成如下形式,需要注意的是,如果沒開啟?deep: true
?選項,當?data.a.b
?發生變動的時候,不會觸發該?OnChangeA
?監聽。
3.屬性類型
構建工具會自動對成員變量應用了?@Component.Property
?裝飾器,不需要用戶手動填寫,
最終的合并策略取決于被裝飾的?成員變量
?的標識符名稱,框架內置了以下幾種。如果不在下表中,會透傳至?VueComponent
?的?options
?對象中。
成員類型 | 名稱 | 功能 |
---|---|---|
property | props | vue的props屬性 |
property | data | vue的data屬性,會被轉換成函數形式, 支持 this,請勿直接寫?data(){} ?函數 |
property | * | 其他未知屬性,直接復制到?Vue ?的?options ?中的對應屬性上 |
props
@Component
export default class Hello {props = {name: {type: String,default: 'haha'},num: Number}
}
上述?props
?成員變量定義,會被直接轉換成到?options
?中對應的?props
。具體完整定義結構請參見 Vue 文檔?API-props。
HelloOption = {props: {name: {type: String,default: 'haha'},num: Number}
}
data
@Component
export default class Hello {props = {name: {type: Number,default: 1},}data = {hello: this.props.name + 2}
}
上述?data
?成員變量定義,會被轉換成 data 函數形式,您無需手動編寫 data 函數。
TestOption = {props: {name: {type: Number,default: 1}, },data: function data() {return {hello: this.props.name + 2}}
}
dependency
上述?<script>
?定義中,沒有說明組件依賴的使用方式,在?.vue
?文件中,推薦使用以下寫法來標記組件依賴,即?<dependency>
?標簽,下面示例中即引用了?./child.vue
?組件。
<template><child></child>
</template>
<dependency component="Child" src="./child.vue" />
標簽屬性
default 導入
針對?ES6 Module
?的?default
?導出或者?commonjs Module
?對象的導出,可使用如下方式引入。
屬性 | 類型 | 默認值 | 備注 |
---|---|---|---|
component | string | 必填 | 引入到?options.components ?的標識符名。 |
src | string | 必填 | 組件來源,同require(src )。 |
lazy | boolean | false | 是否對該組件啟用懶加載(當且僅當被?Vue ?使用到時再進行?require ?加載模塊)。 |
style | string | undefined | 默認不啟用,如果設置了字符串,會根據?${src}/${style} ?的路徑來加載組件對應樣式文件。 |
如下示例:
<dependency component="name" src="source" lazy />
?
member 導入
針對?ES6 Module
?的命名導出,可使用如下方式引入:
屬性 | 類型 | 默認值 | 備注 |
---|---|---|---|
component | string | 必填 | 引入到?options.components ?的多個命名標識符, 必須以花括號?{ ,} ?包括,否則會識別為?default 引入 。 |
src | string | 必填 | 組件來源,同 require(src )。 |
lazy | boolean | false | 是否對該組組件啟用懶加載(當且僅當被?Vue ?使用到時再進行?require ?加載模塊)。 |
如下示例:
<dependency component="{ List, ListItem, AButton }" src="@alipay/antui-vue" lazy />
默認對?@alipay/antui-vue
?組件庫支持?babel-plugin-import
?按需加載。
template
模板的內容結構與 vue 一致。
<template><div>Hello World</div>
</template>
style
可以通過添加?scoped
?屬性標記來使得該樣式只對當前組件生效。
<style lang="less" rel="stylesheet/less" scoped>/* less */
</style>
狀態注入
對于 Kylin 組件, 如果需要使用到?Store
?中的屬性,使用計算屬性把?$store
?對象中的屬性透傳出來是一種不推薦的寫法,如下所示:
@Component
class Hello {// 通過計算屬性來關聯store中的狀態get hello() {return this.$store.state.hello}
}
推薦使用下面的?connect
?機制來透傳?$store
?數據:
- mapStateToProps
- mapActionsToMethods
- mapMethods
接口聲明
@Component({mapStateToProps: Object|Array,mapActionsToMethods: Object|Array,mapMethods: Array|Boolean,mapEvents: Array
})
class Hello {
}
mapStateToProps
把?state
?中的特定鍵值映射到當前組件的?props
?中,其接收參數等價于?Vuex
?提供的?mapState
?輔助函數。
有以下 3 種方式可實現上述功能:
函數方式
說明:把?$store.state
?中名為?bbb
?的數據,映射到名為?aaa
?的?props
?上。
{mapStateToProps: {aaa: (state, getters) => state.bbb}
}
字符串鍵值對方式
說明:把?$store.state
?中名為?bbb
?的數據,映射到名為?aaa
?的?props
?上。
{mapStateToProps: {aaa: 'bbb'}
}
字符串數組方式
說明:
- 把?
$store.state
?中名為?aaa
?的數據,映射到名為?aaa
?的?props
?上。 - 把?
$store.state
?中的名為?bbb
?的數據,映射到名為?bbb
?的props
?上。
{mapStateToProps: ['aaa', 'bbb']
}
mapActionsToMethods
與?Vuex
?中?mapActions
?入參一致,支持使用對象方式(名稱映射)、數組方式(名稱)把在全局?$store
?下配置的?actions
?注入到當前組件的?methods
?中。
@Component({mapActionsToMethods: ['a', 'b']
})
class IndexView {async doSomeAction() {const ret = await this.a(123);// 等價于調用// const ret = await this.$store.dispatch('a', 123);}
}
mapMethods
通過在父子組件之間加一層中間層組件的方式來具體實現?connect
?機制。當父組件調用子組件中特定的?method
?方法時,無法直接訪問子組件(實際訪問到的是中間層組件),需要通過以下配置實現訪問。
@Component({mapMethods: true
})
export default class Child {a() {}
}
<template><div>this is parent<child ref="child"></child></div>
</template>
<script>@Componentexport default class Parent {b() {// 此處可以訪問this.$refs.child.a();}}
</script>
?
吐槽:學這個麒麟框架真的像中了佐二助大招雷遁麒麟一樣難受(╯﹏╰)
?
?
?
?
?