文档

组件

更新时间:

Component 扩充自 Vue 的组件, 提供了 Vue 组件对等的输入参数能力。在代码书写时提供类 class 的装饰器 Decorator 风格。

代码引入

import { Component, Watch } from '@ali/kylin-framework';

组件声明结构

一个组件可以包含数据、JSX 渲染函数、模板、挂载元素、方法、生命周期等 Vue 的 options 选项的对等配置。组件声明包括以下几部分, 分别使用 @Component 和 @Watch 两种不同装饰器进行包装:

  • class 类声明,使用装饰器 @Component。

  • 类成员声明,不使用装饰器。

  • 类成员方法声明,一般不装饰器,除非该方法需要 watch 另外一个已声明的变量。

下面是简单的组件开发演示,具体声明参数参见 组件接口 了解详情。

*.vue 单文件组件

<!-- 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';

  @Component
  class Hello {
    data = {
      name: 'world'
    }
  }

  export default Hello;
</script>

关于 <component> 标签式的组件依赖,参见 组件接口 了解详情。

组件接口

跟 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';
  @Component
  export default class IndexView {
    props = {}
    data = {}
    get comput() { return this.data.c * 2 }
    onClick() {}
    mounted() {}
  }
</script>

上述例子中,有 4 个顶级标签,除了与 Vue 相同的 <template><style><script> 之外,还有一个 <dependency> 标签。

下文将对这 4 个标签的具体作用分别进行阐述。其中 <template><style>vue 中定义一致。

script

class 结构

定义一个 Component ,在代码结构上,使用类 class 的装饰器 Decorator 风格。其中装饰器有 @Component 和 @Watch 这 2 种,通过以下方式引入。

import { Component, Watch } from '@ali/kylin-framework';

@Component
export default class Hello {

}

方法类型

组件以 class 形式声明,必须对该 class 进行装饰器修饰。在 class 内部,成员变量是不需要被手动处理的,在构建过程中通过 babel 插件自动进行处理,而成员函数一般不需要装饰器挂载,除非是使用 @Watch 的场景,其中 @Component 会处理的属性如下表所示。

成员类型

名称

功能

get/set property

*

用以转换成 Vue 的 computed 计算属性,可以直接通过 this[varName] 调用。

beforeCreate

生命周期

生命周期方法,与 Vue 对等。

created

生命周期

生命周期方法,与 Vue 对等。

beforeMount

生命周期

生命周期方法,与 Vue 对等。

mounted

生命周期

生命周期方法,与 Vue 对等。

beforeUpdate

生命周期

生命周期方法,与 Vue 对等。

updated

生命周期

生命周期方法,与 Vue 对等。

beforeDestroy

生命周期

生命周期方法,与 Vue 对等。

destroyed

生命周期

生命周期方法,与 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 也会被提取,如果同时存在 gettersetter 则会被一起提取。

生命周期函数

@Component 
export default class Hello {
  created() {}
  mounted() {}
}

上述 createdmounted 生命周期函数,会被提取为数组。

TestOption = {
  created: [function created(){}],
  mounted: [function mounted(){}],
}

支持的生命周期方法名如下,beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatedbeforeDestroydestroyed

Watch

该装饰器的出现,只是因为 watch 需要有以下几个要素:

  • 被监听的变量名

  • 监听选项

  • 触发函数

用法

完整的 @Watch 接口如下表所示。

function Watch( key: string [, option: Object = {} ] ): PropertyDecorator

参数名

类型

用途

key

string

监听的参数名,来自 computeddataprops 三者之一。

option

deep

boolean

若监听的是复杂对象,其内层数据变更是否触发,默认为 false

immediate

boolean

立即以表达式的当前值触发回调,默认为 false

示例

  • 对于 @Watch 装饰的成员函数,支持对成员函数配置多个变量的监听,如下同时对 ac 的变化进行了监听,如果任何一个发生变化,会触发 OnChangeA 成员方法。

  • 如下,OnChangeA 本质是成员方法,所以他也会和其他成员方法一起被提取到 methods 块中,那么必须保证没有与其他方法重名。

  • 如果对 Watch 有额外配置项,请按 @Watch('a', {deep: false}) 的方法传入。配置项请参考 watch 配置项

@Component
class WTest {

  data = {
    a: {
      b: 2
    },
    c: 3
  }

  @Watch('c')
  @Watch('a', {deep: false}) 
  OnChangeA(newVal, oldVal) {

  }
}
重要

以上对 data.a 的监听,会转换成如下形式,需要注意的是,如果没开启 deep: true 选项,当 data.a.b 发生变动的时候,不会触发该 OnChangeA 监听。

属性类型

构建工具会自动对成员变量应用了 @Component.Property 装饰器,不需要用户手动填写,最终的合并策略取决于被装饰的成员变量的标识符名称,框架内置了以下几种。如果不在下表中,会透传至 VueComponentoptions 对象中。

成员类型

名称

功能

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。

HelloOption = {
  props: {
    name: {
      type: String,
      default: 'haha'
    },
    num: Number
  }
}

具体完整定义结构请参见 Vue 文档 API-props

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

<style lang="less" rel="stylesheet/less">
    /* less */
</style>

其中,可以通过添加 scoped 属性标记来使得该样式只对当前组件生效。

<style lang="less" rel="stylesheet/less" scoped>
    /* less */
</style>

状态注入

推荐使用下面的 connect 机制来透传 $store 数据:

  1. 接口声明

  2. 透传数据,有以下 3 种方式:

对于 Kylin 组件, 如果需要使用到 Store 中的属性,不推荐使用计算属性把 $store 对象中的属性透传出来,如下所示:

@Component 
class Hello {
  // 通过计算属性来关联 store 中的状态
  get hello() {
    return this.$store.state.hello
  }
}

接口声明

@Component({
  mapStateToProps: Object|Array,
  mapActionsToMethods: Object|Array,
  mapMethods: Array|Boolean,
  mapEvents: Array
})
class Hello {

}

mapStateToProps

把 state 中的特定键值映射到当前组件的 props 中,其接收参数等价于 Vuex 提供的 辅助函数

有以下 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>
  @Component
  export default class Parent {
    b() {
      // 此处可以访问
      this.$refs.child.a();
    }
  }
</script>
  • 本页导读 (0)
文档反馈