# 高级组件

# 字典下拉框

字典下拉框是普通下拉框的进一步封装,支持直接传入获取数据的方法,支持缓存数据。(同时使用两个字典下拉框,即使设置了缓存,也可能会请求两次,这是因为二者同时生成,同时请求,没有明显的顺序)

通过设置cache可以配置缓存,cache.type设置缓存类型为local或session,分别对应localStroage、sessionStroage,cache.expire设置缓存时间,单位为秒,设置为空时不缓存

<template>
  <div>
    <normal-switch
      v-model="textModel"
      active-text="文本模式"
      inactive-text="表单模式"
    ></normal-switch>
    <RenderForm :fields="fields" :textModel="textModel"></RenderForm>
  </div>
</template>
<script>
const fetchCategory = () => {
  console.log("访问fetchCategory接口");
  return Promise.resolve([
    { value: 1, label: "美食" },
    { value: 2, label: "地推活动" },
    { value: 3, label: "线下主题活动" },
    { value: 4, label: "单纯品牌曝光" },
  ]);
};
export default {
  name: "DictSelect",
  data() {
    return {
      textModel: false,
      fields: [
        {
          label: "字典下拉",
          children: [
            {
              type: "dict",
              key: "key01",
              dict: fetchCategory,
              dictName: "category",
              cache: {
                type: "session",
                expire: 60,
              },
            },
            {
              type: "dict",
              key: "key02",
              dict: fetchCategory,
              dictName: "category",
            },
          ],
        },
      ],
    };
  },
};
</script>
<style lang="css" scoped></style>
Expand Copy

# 搜索下拉框

搜索下拉框支持通过关键字搜索选项,通过设置canEmpty是否允许空值搜索;searchFn是查询方法,接收一个参数,用户输入的值,返回一个数组;getOption通过数据的值获取完整的数据,在表单编辑和查看状态时,获取完整的数据展示出来。

<template>
  <div>
    <normal-switch
      v-model="textModel"
      active-text="文本模式"
      inactive-text="表单模式"
    ></normal-switch>
    <RenderForm :fields="fields" :textModel="textModel"></RenderForm>
  </div>
</template>
<script>
const list = [
  "Alabama",
  "Alaska",
  "Arizona",
  "Arkansas",
  "California",
  "Colorado",
  "Connecticut",
  "Delaware",
  "Florida",
  "Georgia",
  "Hawaii",
  "Idaho",
  "Illinois",
  "Indiana",
  "Iowa",
  "Kansas",
  "Kentucky",
  "Louisiana",
  "Maine",
  "Maryland",
  "Massachusetts",
  "Michigan",
  "Minnesota",
  "Mississippi",
  "Missouri",
  "Montana",
  "Nebraska",
  "Nevada",
  "New Hampshire",
  "New Jersey",
  "New Mexico",
  "New York",
  "North Carolina",
  "North Dakota",
  "Ohio",
  "Oklahoma",
  "Oregon",
  "Pennsylvania",
  "Rhode Island",
  "South Carolina",
  "South Dakota",
  "Tennessee",
  "Texas",
  "Utah",
  "Vermont",
  "Virginia",
  "Washington",
  "West Virginia",
  "Wisconsin",
  "Wyoming",
];
const searchList = (query) => {
  console.log("访问searchList接口");
  return Promise.resolve(
    list
      .map((item, index) => {
        return { value: index, label: item };
      })
      .filter((item) => {
        return item.label.toLowerCase().indexOf(query.toLowerCase()) > -1;
      })
  );
};
const getOption = (value) => {
  return Promise.resolve({
    value,
    label: list[value],
  });
};
export default {
  name: "DictSelect",
  data() {
    return {
      textModel: false,
      fields: [
        {
          label: "搜索下拉",
          children: [
            {
              type: "search",
              label: "搜索下拉",
              key: "key01",
              searchFn: searchList,
              getOption,
            },
            {
              type: "search",
              label: "默认值",
              key: "key02",
              searchFn: searchList,
              defaultValue: 1,
              getOption,
            },
            {
              type: "search",
              label: "允许空值查询",
              key: "key03",
              searchFn: searchList,
              canEmpty: true,
              getOption,
            },
          ],
        },
      ],
    };
  },
};
</script>
<style lang="css" scoped></style>
Expand Copy

# 表格选择框

<template>
  <div>
    <normal-switch
      v-model="textModel"
      active-text="文本模式"
      inactive-text="表单模式"
    ></normal-switch>
    <RenderForm :fields="fields" :textModel="textModel"></RenderForm>
  </div>
</template>
<script>
const list = [
  {
    id: 1044,
    name: "123334",
    note: "333333",
    type: "manual",
    num: 0,
    edate: "2022-01-06T08:10:00Z",
  },
  {
    id: 1043,
    name: "业主黑名单",
    note: "专门屏蔽XXX类业主",
    type: "manual",
    num: 0,
    edate: "2022-01-06T08:07:48Z",
  },
  {
    id: 1042,
    name: "哈哈哈",
    note: "222",
    type: "manual",
    num: 1,
    edate: "2022-01-06T08:03:00Z",
  },
  {
    id: 1041,
    name: "哈哈哈哈哈",
    note: "哈哈哈哈",
    type: "manual",
    num: 3,
    edate: "2021-12-28T07:46:42Z",
  },
  {
    id: 1029,
    name: "测试62152109",
    note: "组备注",
    type: "manual",
    num: 5,
    edate: "2021-11-11T11:33:37Z",
  },
  {
    id: 1028,
    name: "测试16610391",
    note: "组备注",
    type: "manual",
    num: 1,
    edate: "2021-11-11T11:32:57Z",
  },
  {
    id: 1027,
    name: "测试03281310",
    note: "组备注",
    type: "manual",
    num: 1,
    edate: "2021-11-11T11:23:00Z",
  },
  {
    id: 1026,
    name: "测试61772045",
    note: "组备注",
    type: "manual",
    num: 0,
    edate: "2021-11-11T11:14:36Z",
  },
  {
    id: 1025,
    name: "测试",
    note: "11111111111111111111",
    type: "manual",
    num: 853,
    edate: "2021-11-02T06:12:49Z",
  },
];
const fetchData = (params) => {
  console.log("访问fetchData接口,参数是", params);
  const { page, rows } = params;
  return Promise.resolve({
    list: list.slice((page - 1) * rows, page * rows),
    total: list.length,
  });
};
const getItems = (ids) => {
  console.log("访问getItems接口,参数是", ids);
  return Promise.resolve(list.filter((item) => ids.includes(item.id)));
};
export default {
  name: "Table",
  data() {
    return {
      textModel: false,
      fields: [
        {
          label: "表格",
          children: [
            {
              label: "普通输入框",
              key: "input",
              type: "input",
            },
            {
              label: "表格选择框",
              key: "group",
              type: "table",
              title: "选择分组",
              fetchData,
              getItems,
              searchField: [
                {
                  key: "name",
                  label: "分组名称",
                },
              ],
              columns: [
                {
                  key: "name",
                  label: "分组名称",
                },
                {
                  key: "num",
                  label: "成员人数",
                },
              ],
            },
          ],
        },
      ],
    };
  },
};
</script>
<style lang="css" scoped></style>
Expand Copy

# 子表单

子表单是在表单中嵌入表单,不支持循环设置子表单(子表单内不支持子表单);子表单配置和表单配置相似,headerLabel设置子表单名称。 在watcher监听表单数据,对与子表单只支持监听整个子表单数据的变化,子表单任意数据变化都都会触发子表单的监听事件。

<template>
  <div>
    <normal-switch
      v-model="textModel"
      active-text="文本模式"
      inactive-text="表单模式"
    ></normal-switch>
    <RenderForm
      :fields="fields"
      :textModel="textModel"
      :watcher="watcher"
    ></RenderForm>
  </div>
</template>
<script>
export default {
  name: "ChildForm",
  data() {
    return {
      textModel: false,
      watcher: {
        group(value, data) {
          // 子表单只能监听整个表单的数据变化,更精确的变化可以直接对比前后的顺序
          data.name = `子表单长度:${value.length}`;
        },
      },
      fields: [
        {
          label: "子表单组件",
          children: [
            {
              key: "name",
              label: "普通的输入框",
            },
            {
              type: "form",
              key: "group",
              label: "子表单",
              headerLabel: "子表单",
              fields: [
                {
                  key: "key01",
                  label: "子表单的输入框",
                },
              ],
            },
          ],
        },
      ],
    };
  },
};
</script>
<style lang="css" scoped></style>
Expand Copy

# slot

支持slotslot-single两种类型的slot,slot是在form-item中插入内容,slot-single是使用内容替代form-item,所以slot-singlelabel是无效的,会占据更多的位置。

<template>
  <RenderForm :fields="fields">
    <template #card>
      <el-card class="box-card">
        <div v-for="o in 4" :key="o" class="text item">
          {{ "列表内容 " + o }}
        </div>
      </el-card>
    </template>
    <template #submit>
      <el-button type="primary">提交</el-button>
    </template>
  </RenderForm>
</template>
<script>
export default {
  name: "SlotComp",
  data() {
    return {
      fields: [
        {
          label: "Slot",
          children: [
            {
              label: "普通输入框",
              key: "input",
            },
            {
              label: "label标签无效",
              name: "card",
              type: "slot-single",
            },
            {
              label: "",
              type: "slot",
              name: "submit",
            },
          ],
        },
      ],
    };
  },
};
</script>
<style lang="css" scoped>
.text {
  font-size: 14px;
}

.item {
  padding: 18px 0;
}

.box-card {
  width: 480px;
}
</style>
Expand Copy