vue 关联表单项组件,常用于组合条件

QQ图片20210623093824.png

这是一个 vue 简单组件, 用来实现一个表单关联的功能。例如一些条件生成:

  • 当 - 发言人 - 为 - 坐席
  • 当 - 发言人 - 为 - 客户
  • 当 - 发言内容 - 包含 - 你好
  • 当 - 发言内容 - 不包含 - 你好

像上面的上级选项为某个值之后,后面是根据这个值又首先新的选项。

<template>
  <div class="about">
    <span>{{ rootTable.pre }}</span>
    <template v-for="(tableValueItem, tableValueIndex) in filterOptions">
      <el-cascader
        :key="`el-cascader${tableValueIndex}`"
        v-if="[`el-cascader`].includes(getItem(tableValueIndex).type)"
        v-model="tableValue[tableValueIndex]"
        :options="getOptions(tableValueIndex)"
        v-bind="getItem(tableValueIndex).props"
        clearable
      ></el-cascader>
      <el-select
        v-else
        :key="`el-select${tableValueIndex}`"
        clearable
        v-model="tableValue[tableValueIndex]"
        @change="(val) => change(val, tableValueIndex)"
        :placeholder="getItem(tableValueIndex).placeholder"
        :multiple="getItem(tableValueIndex).multiple"
        :allow-create="getItem(tableValueIndex).allowCreate"
        :filterable="getItem(tableValueIndex).allowCreate"
        :default-first-option="getItem(tableValueIndex).allowCreate"
      >
        <el-option
          :key="item.value"
          v-for="item in getOptions(tableValueIndex)"
          :label="item.label"
          :value="item.value"
        >
        </el-option>
      </el-select>
      <span :key="`span${tableValueIndex}`">{{ getSub(tableValueIndex) }}</span>
    </template>
  </div>
</template>
<script>
/**
- 只有选择父项目时才会出现子项
- 父项值改变时, 清空子项的值
 */
export default {
  model: {
    prop: "defaultValue",
    event: "update",
  },
  props: {
    // 默认值, 可以用 v-model 绑定
    defaultValue: {
      type: Array,
      default() {
        return ["发言内容发言内容", "包含包含", "关键词关键词", ["你好"]];
      },
    },

    // 标签数据, 可以优化为数据公用表, 然后在 rootTable 中通过 optionsSource 选项引用
    tagData: {
      default() {
        return [
          {
            value: "zhinan",
            sub: `时`,
            label: "指南",
            children: [
              {
                value: "shejiyuanze",
                label: "设计原则",
                children: [
                  {
                    value: "yizhi",
                    label: "一致",
                  },
                  {
                    value: "fankui",
                    label: "反馈",
                  },
                  {
                    value: "xiaolv",
                    label: "效率",
                  },
                  {
                    value: "kekong",
                    label: "可控",
                  },
                ],
              },
              {
                value: "daohang",
                label: "导航",
                children: [
                  {
                    value: "cexiangdaohang",
                    label: "侧向导航",
                  },
                  {
                    value: "dingbudaohang",
                    label: "顶部导航",
                  },
                ],
              },
            ],
          },
          {
            value: "zujian",
            label: "组件",
            children: [
              {
                value: "basic",
                label: "Basic",
                children: [
                  {
                    value: "layout",
                    label: "Layout 布局",
                  },
                  {
                    value: "color",
                    label: "Color 色彩",
                  },
                  {
                    value: "typography",
                    label: "Typography 字体",
                  },
                  {
                    value: "icon",
                    label: "Icon 图标",
                  },
                  {
                    value: "button",
                    label: "Button 按钮",
                  },
                ],
              },
              {
                value: "form",
                label: "Form",
                children: [
                  {
                    value: "radio",
                    label: "Radio 单选框",
                  },
                  {
                    value: "checkbox",
                    label: "Checkbox 多选框",
                  },
                  {
                    value: "input",
                    label: "Input 输入框",
                  },
                  {
                    value: "input-number",
                    label: "InputNumber 计数器",
                  },
                  {
                    value: "select",
                    label: "Select 选择器",
                  },
                  {
                    value: "cascader",
                    label: "Cascader 级联选择器",
                  },
                  {
                    value: "switch",
                    label: "Switch 开关",
                  },
                  {
                    value: "slider",
                    label: "Slider 滑块",
                  },
                  {
                    value: "time-picker",
                    label: "TimePicker 时间选择器",
                  },
                  {
                    value: "date-picker",
                    label: "DatePicker 日期选择器",
                  },
                  {
                    value: "datetime-picker",
                    label: "DateTimePicker 日期时间选择器",
                  },
                  {
                    value: "upload",
                    label: "Upload 上传",
                  },
                  {
                    value: "rate",
                    label: "Rate 评分",
                  },
                  {
                    value: "form",
                    label: "Form 表单",
                  },
                ],
              },
              {
                value: "data",
                label: "Data",
                children: [
                  {
                    value: "table",
                    label: "Table 表格",
                  },
                  {
                    value: "tag",
                    label: "Tag 标签",
                  },
                  {
                    value: "progress",
                    label: "Progress 进度条",
                  },
                  {
                    value: "tree",
                    label: "Tree 树形控件",
                  },
                  {
                    value: "pagination",
                    label: "Pagination 分页",
                  },
                  {
                    value: "badge",
                    label: "Badge 标记",
                  },
                ],
              },
              {
                value: "notice",
                label: "Notice",
                children: [
                  {
                    value: "alert",
                    label: "Alert 警告",
                  },
                  {
                    value: "loading",
                    label: "Loading 加载",
                  },
                  {
                    value: "message",
                    label: "Message 消息提示",
                  },
                  {
                    value: "message-box",
                    label: "MessageBox 弹框",
                  },
                  {
                    value: "notification",
                    label: "Notification 通知",
                  },
                ],
              },
              {
                value: "navigation",
                label: "Navigation",
                children: [
                  {
                    value: "menu",
                    label: "NavMenu 导航菜单",
                  },
                  {
                    value: "tabs",
                    label: "Tabs 标签页",
                  },
                  {
                    value: "breadcrumb",
                    label: "Breadcrumb 面包屑",
                  },
                  {
                    value: "dropdown",
                    label: "Dropdown 下拉菜单",
                  },
                  {
                    value: "steps",
                    label: "Steps 步骤条",
                  },
                ],
              },
              {
                value: "others",
                label: "Others",
                children: [
                  {
                    value: "dialog",
                    label: "Dialog 对话框",
                  },
                  {
                    value: "tooltip",
                    label: "Tooltip 文字提示",
                  },
                  {
                    value: "popover",
                    label: "Popover 弹出框",
                  },
                  {
                    value: "card",
                    label: "Card 卡片",
                  },
                  {
                    value: "carousel",
                    label: "Carousel 走马灯",
                  },
                  {
                    value: "collapse",
                    label: "Collapse 折叠面板",
                  },
                ],
              },
            ],
          },
          {
            value: "ziyuan",
            sub: `时`,
            label: "资源",
            children: [
              {
                value: "axure",
                label: "Axure Components",
              },
              {
                value: "sketch",
                label: "Sketch Templates",
              },
              {
                value: "jiaohu",
                label: "组件交互文档",
              },
            ],
          },
        ];
      },
    },

    /**
      - 渲染表单的数据, 当上一级表单项有值后才会子项
      pre - 在某个表单项前面
      sub - 在某个表单项后面, 当表单项有值后才会显示
      options - 子项的可选项
      type - 可以根据此 type 来渲染组件, 默认为普通 select, 可以优化为动态渲染组件以及添加组件 props 选项
        - el-cascader 级联选择
      label - 选项的 label
      value - 选项的 value
      multiple - 是否多选
      allowCreate - 是否显示清除图片
    */
    rootTable: {
      type: Object,
      default() {
        console.log(`tagDatatagData`, this.tagData);
        return {
          pre: `当`,
          options: [
            {
              label: `发言内容`,
              value: `发言内容发言内容`,
              sub: `中`,
              options: [
                {
                  label: `不包含`,
                  value: `不包含不包含`,
                  sub: ``,
                  options: [
                    {
                      label: `语义标签`,
                      value: `语义标签语义标签`,
                      sub: `中的`,
                      type: `el-cascader`,
                      optionsSource: `tagData`,
                    },
                    {
                      label: `关键词`,
                      value: `关键词关键词`,
                      placeholder: `请输入`,
                      sub: `中的`,
                      multiple: true,
                      allowCreate: true,
                      forcedDisplay: true,
                    },
                  ],
                },
                {
                  label: `包含`,
                  value: `包含包含`,
                  sub: ``,
                  options: [
                    {
                      label: `语义标签`,
                      value: `语义标签语义标签`,
                      sub: `中的`,
                      type: `el-cascader`,
                      optionsSource: `tagData`,
                    },
                    {
                      label: `关键词`,
                      value: `关键词关键词`,
                      placeholder: `请输入`,
                      sub: `中的`,
                      multiple: true,
                      allowCreate: true,
                      forcedDisplay: true,
                    },
                  ],
                },
              ],
            },
            {
              label: `发言人`,
              value: `发言人发言人`,
              sub: `为`,
              options: [
                {
                  label: `用户`,
                  value: `用户用户`,
                  sub: ``,
                  options: [],
                },
                {
                  label: `坐席`,
                  value: `坐席坐席`,
                  sub: ``,
                  options: [],
                },
                {
                  label: `所有`,
                  value: `所有所有`,
                  sub: ``,
                  options: [],
                },
              ],
            },
          ],
        };
      },
    },
  },
  data() {
    return {
      table: this.rootTable.options,
      tableValue: this.defaultValue,
    };
  },
  watch: {
    defaultValue: {
      handler(val) {
        this.$emit(`update:defaultValue`, val);
      },
      deep: true,
    },
  },
  created() {
    // this.getOptions(`选项1选项1`, `选项11选项11`)
  },
  computed: {
    filterOptions() {
      let curItem = this.getCurItem({ index: undefined });
      console.log(`curItemcurItem`, curItem);

      let list = this.tableValue.length ? this.tableValue : [undefined];
      // 如果还有子项并且父选项有值时, 那么就加载子项选择器
      if (
        curItem.forcedDisplay ||
        (this.getOptions().length &&
          [``, undefined].includes(list.slice(-1)[0]) === false)
      ) {
        list.push(undefined);
      }
      return list;
    },
    sub() {
      const curItem =
        this.table.find((item) => item.value === this.tableValue[0]) || {};
      return curItem.sub;
    },
  },
  methods: {
    getCurItem({ keys, index }) {
      if (keys === undefined) {
        keys =
          index === undefined
            ? this.tableValue
            : this.tableValue.slice(0, index);
      }
      let curItem = this.rootTable;
      keys.forEach((key) => {
        curItem =
          (curItem.options || []).find((item) => {
            return (
              item.value === key ||
              (typeof key === `object` ? key.includes(item.value) : false) // 处理多选时如果包含其中一个选项则返回
            );
          }) || {};
      });
      return curItem;
    },
    change(val, index) {
      console.log(`val, key`, val, index);
      this.tableValue.splice(index + 1, this.tableValue.length); // 当父项值改变的时候, 删除所有子项的值
    },
    getOptions(index) {
      // 根据值获取选项
      let curItem = this.getCurItem({ index });
      curItem.options = this[curItem.optionsSource] || curItem.options;
      console.log(`curItem.options`, curItem.options);
      return curItem.options || [];
    },
    getItem(index) {
      let curItem = this.getCurItem({ index });
      return curItem;
    },
    getSub(index) {
      // 根据值获取选项
      if (
        // 只有所选择的项存在值时, 才显示后缀
        this.tableValue[index] === undefined ||
        this.tableValue[index] === ``
      ) {
        return ``;
      }
      const keys = this.tableValue.slice(0, index + 1);
      let curItem = this.getCurItem({ keys });
      console.log(`getSubgetSubgetSubgetSub`, keys, curItem);
      return curItem.sub;
    },
  },
  components: {},
};
</script>
posted @ 2021-06-23 09:45  程序媛李李李李蕾  阅读(1083)  评论(0)    收藏  举报