Skip to content

数据源

1. 功能说明

平台数据属性统一为dataSource属性,可以直接绑定后端逻辑,获取远程数据。

以下以选择器组件为例:

2. 功能实现

2.1 增加数据源相关属性

向 api.ts 文件中写入数据源相关属性。

以下以选择器组件为例:包含“数据源”、“数据类型”、“文本字段”、“值字段”属性以及重新加载数据源的组件逻辑(reload)。

typescript
@Component({
  title: '选择器',
  description: '选择器',
})
export class SelectOptions<T, V> extends ViewComponent {
  constructor(options?: Partial<SelectOptions<T, V>>) {
    super();
  }

  @Method({
    title: '重新加载数据',
    description: '重新加载数据'
  })
  reload(): void {} // 需要提供重新加载数据源的方法
}
// api.ts
export class SelectOptions<T, V> extends ViewComponentOptions {
  @Prop({
    group: '数据属性',
    title: '数据源',
    description: '展示数据的输入源,可设置为数据集对象或者返回数据集的逻辑',
    docDescription: '列表展示的数据。数据源可以绑定变量或者逻辑。变量或逻辑的返回值可以是数组,也可以是对象。对象格式为{list:[], total:10}',
  })
  dataSource: { list: nasl.collection.List<T>; total: nasl.core.Integer } | nasl.collection.List<T>;

  @Prop({
    group: '数据属性',
    title: '数据类型',
    description: '数据源返回的数据结构的类型,自动识别类型进行展示说明',
    docDescription: '列表每一行的数据类型。该属性为展示属性,由数据源推倒得到,无需填写。',
  })
  dataSchema: T;


  @Prop({
    group: '数据属性',
    title: '文本字段',
    description: '选项文本的字段名',
    setter: {
      concept: "PropertySelectSetter"
    }
  })
  textField: (item: T) => any;


  @Prop({
    group: '数据属性',
    title: '值字段',
    description: '选项文本的字段名',
    setter: {
      concept: "PropertySelectSetter"
    }
  })
  valueField: (item: T) => V = ((item: T) => item.value) as any;;
}

2.2 组件内部加载数据和渲染

Vue2
React

参考Element UI Select支持数据源示例。

typescript
<template>
<el-select v-bind="$attrs" v-on="$listeners" :loading="loading">
  <template v-if="!!dataSource">
    <el-option
      v-for="item in list"
      :key="lodashGet(item, valueField)"
      :label="lodashGet(item, textField)"
      :value="lodashGet(item, valueField)">
    </el-option>
  </template>
  <slot v-else></slot>
</el-select>
</template>
<script>
import lodashGet from 'lodash/get';

export default {
  props: {
    dataSource: {
      type: [Array, Object, Function]
    },
    textField: {
      type: String,
      default: 'text',
    },
    valueField: {
      type: String,
      default: 'value',
    },
  },
  data() {
    return {
      list: [],
      loading: false,
    };
  },
  watch: {
    dataSource: {
      handler() {
        this.$nextTick(() => {
          this.loadDataSource();
        });
      },
      immediate: true
    },
  },
  methods: {
    lodashGet,
    normalizeData(data) {
      if (Array.isArray(data)) {
        return data;
      }

      if (typeof data === 'object' && Array.isArray(data.list)) {
        return data.list;
      }

      return [];
    },

    async loadDataSource() {
      if (typeof this.dataSource === 'function') {
        this.loading = true;
        const data = await this.dataSource({});
        this.list = this.normalizeData(data);
        this.loading = false;
      } else {
        this.list = this.normalizeData(this.dataSource);
      }
    },
    async reload() {
      return this.loadDataSource();
    },
  },
}
</script>