schema-form.md 17.5 KB

Schema Form 方案表单

通过配置JSON Schema的方式快速生成一个表单

6a3e9fa03a9e62888fd3096196dcc68e3e3bb90a/examples/views/docs/component/schema-form.md#">基础用法

schema设置配置项,其中props参数与eagle-form组件参数相同,items则对应eagle-form-item组件,默认参数为<component>组件与eagle-form-item组件参数的并集。

::: snippet 基础示例

<template>
  <eagle-schema-form v-model="form" :schema="schema"></eagle-schema-form>
</template>

<script>
export default {
  data() {
    return {
      form: {
        name: '张三',
        age: 27,
        address: '上海市青浦区华新镇纪鹤公路1988号',
      },
      schema: {
        props: { labelWidth: '70px', span: 12 },
        items: [
          { is: 'el-input', prop: 'name', label: '姓名' },
          { is: 'el-input-number', prop: 'age', label: '年龄' },
          { is: 'el-input', props: { type: 'textarea' }, prop: 'address', label: '住址', span: 24 },
        ]
      },
    };
  },
};
</script>

:::

6a3e9fa03a9e62888fd3096196dcc68e3e3bb90a/examples/views/docs/component/schema-form.md#">表单校验

配置下的props对应eagle-form的参数,可以在此统一配置rules;配置下的items的每一项都对应eagle-form-item,也可以直接配置rules设置该项的校验规则。

::: snippet 设置props下的校验规则示例

<template>
  <eagle-schema-form v-model="form" :schema="schema"></eagle-schema-form>
</template>

<script>
export default {
  data() {
    return {
      form: {
        name: '张三',
        age: 27,
        address: '上海市青浦区华新镇纪鹤公路1988号',
      },
      schema: {
        props: {
          labelWidth: '70px',
          size: 'small',
          span: 12,
          rules: {
            name: [{ required: true, message: '请输入姓名' }],
            age: [{ required: true, message: '请输入有效年龄' }],
          }
        },
        items: [
          { is: 'el-input', prop: 'name', label: '姓名' },
          { is: 'el-input-number', prop: 'age', label: '年龄' },
          { is: 'el-input', props: { type: 'textarea' }, prop: 'address', label: '住址', span: 24 },
        ]
      },
    };
  },
};
</script>

:::

::: snippet 设置items下的校验规则示例

<template>
  <eagle-schema-form v-model="form" :schema="schema"></eagle-schema-form>
</template>

<script>
export default {
  data() {
    return {
      form: {
        name: '张三',
        age: 27,
        address: '上海市青浦区华新镇纪鹤公路1988号',
      },
      schema: {
        props: { labelWidth: '70px', size: 'small', span: 12 },
        items: [
          { is: 'el-input', prop: 'name', label: '姓名', rules: [{ required: true, message: '请输入姓名' }] },
          { is: 'el-input-number', prop: 'age', label: '年龄', rules: [{ required: true, message: '请输入有效年龄' }] },
          { is: 'el-input', props: { type: 'textarea' }, prop: 'address', label: '住址', span: 24 },
        ]
      },
    };
  },
};
</script>

:::

6a3e9fa03a9e62888fd3096196dcc68e3e3bb90a/examples/views/docs/component/schema-form.md#">表单提交

表单会默认提供一个footer插槽,并提供表单的提交、取消、重置等方法,且相关方法都有对应的事件监听。也可以不使用插槽提供的方法直接自定义。

::: snippet 配置footer插槽提供触发方法的示例

<template>
  <eagle-schema-form v-model="form" :schema="schema" @submit="onSubmit" @reset="onReset" @cancel="onCancel">
    <template #footer="{ submit, reset, cancel }">
      <eagle-form-item>
        <el-button type="primary" @click="submit">确定</el-button>
        <el-button plain @click="reset">重置</el-button>
        <el-button plain @click="cancel">取消</el-button>
      </eagle-form-item>
    </template>
  </eagle-schema-form>
</template>

<script>
export default {
  data() {
    return {
      form: {
        name: '张三',
        age: 27,
        address: '上海市青浦区华新镇纪鹤公路1988号',
      },
      schema: {
        props: { labelWidth: '70px', size: 'small', span: 12 },
        items: [
          { is: 'el-input', prop: 'name', label: '姓名', rules: [{ required: true, message: '请输入姓名' }] },
          { is: 'el-input-number', prop: 'age', label: '年龄', rules: [{ required: true, message: '请输入有效年龄' }] },
          { is: 'el-input', props: { type: 'textarea' }, prop: 'address', label: '住址', span: 24 },
        ]
      },
    };
  },
  methods: {
    onSubmit(value) {
      console.log(value);
    },
    onReset() {
      console.log('reset');
    },
    onCancel() {
      console.log('cancal');
    }
  }
};
</script>

:::

::: snippet 自定义提交的示例

<template>
  <eagle-schema-form ref="form" v-model="form" :schema="schema" @submit="onSubmit" @reset="onReset" @cancel="onCancel">
    <template #footer>
      <eagle-form-item>
        <el-button type="primary" @click="onSubmit">确定</el-button>
        <el-button plain @click="onReset">重置</el-button>
        <el-button plain @click="onCancel">取消</el-button>
      </eagle-form-item>
    </template>
  </eagle-schema-form>
</template>

<script>
export default {
  data() {
    return {
      form: {
        name: '张三',
        age: 27,
        address: '上海市青浦区华新镇纪鹤公路1988号',
      },
      schema: {
        props: { labelWidth: '70px', size: 'small', span: 12 },
        items: [
          { is: 'el-input', prop: 'name', label: '姓名', rules: [{ required: true, message: '请输入姓名' }] },
          { is: 'el-input-number', prop: 'age', label: '年龄', rules: [{ required: true, message: '请输入有效年龄' }] },
          { is: 'el-input', props: { type: 'textarea' }, prop: 'address', label: '住址', span: 24 },
        ]
      },
    };
  },
  methods: {
    onSubmit() {
      this.$refs.form.validate(valid => {
        if (valid) {
          console.log(this.form);
        }
      });
    },
    onReset() {
      this.$refs.form.resetFields();
    },
    onCancel() {
      console.log('cancal');
    }
  }
};
</script>

:::

6a3e9fa03a9e62888fd3096196dcc68e3e3bb90a/examples/views/docs/component/schema-form.md#">显示状态

支持配置ifshow对表单项进行v-ifv-show逻辑的设置。

::: snippet 隐藏表单项的示例

<template>
  <eagle-schema-form v-model="form" :schema="schema"></eagle-schema-form>
</template>

<script>
export default {
  data() {
    return {
      form: {
        name: '张三',
        age: 27,
        address: '上海市青浦区华新镇纪鹤公路1988号',
      },
      schema: {
        props: { labelWidth: '70px', size: 'small', span: 12 },
        items: [
          { is: 'el-input', prop: 'id', props: { disabled: true }, label: 'ID', show: false },
          { is: 'el-input', prop: 'name', label: '姓名', rules: [{ required: true, message: '请输入姓名' }] },
          { is: 'el-input-number', prop: 'age', label: '年龄', rules: [{ required: true, message: '请输入有效年龄' }] },
          { is: 'el-input', props: { type: 'textarea' }, prop: 'address', label: '住址', span: 24 },
          { is: 'el-input', prop: 'package', label: '包裹', span: 24, if: false },
        ]
      },
    };
  },
};
</script>

:::

6a3e9fa03a9e62888fd3096196dcc68e3e3bb90a/examples/views/docs/component/schema-form.md#">动态规则

某些情况下,表单中的某一项根据另一项的值来做当前项显示状态校验规则标签名称的动态判断。支持将任意表单配置项的任意参数改写为function类型,参数提供valuemodelonInput等。

::: snippet 动态规则仅在配置项中有效,配置项子节点中无效

<template>
  <eagle-schema-form v-model="form" :schema="schema" @submit="onSubmit" @reset="onReset" @cancel="onCancel">
    <template #footer="{ submit, reset, cancel }">
      <eagle-form-item>
        <el-button type="primary" @click="submit">确定</el-button>
        <el-button plain @click="reset">重置</el-button>
        <el-button plain @click="cancel">取消</el-button>
      </eagle-form-item>
    </template>
  </eagle-schema-form>
</template>

<script>
export default {
  data() {
    return {
      form: {
        name: '',
        age: '',
        address: '',
      },
      schema: {
        props: { labelWidth: '70px', size: 'small', span: 12 },
        items: [
          { is: 'el-input', prop: 'name', label: '姓名', rules: [{ required: true, message: '请输入姓名' }] },
          { is: 'el-input-number', prop: 'age', label: '年龄', rules: [{ required: true, message: '请输入有效年龄' }], if({ model }) { return model.name } },
          { is: 'el-input', props: { type: 'textarea' }, prop: 'address', label: '住址', span: 24,
            if({ model }) { return model.age },
            rules({ model }) {
              return model.address ? [{ required: true, min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'input' }] : [{ required: false }];
            }
          },
        ]
      },
    };
  },
  methods: {
    onSubmit(value) {
      console.log(value);
    },
    onReset() {
      console.log('reset');
    },
    onCancel() {
      console.log('cancal');
    }
  }
};
</script>

:::

6a3e9fa03a9e62888fd3096196dcc68e3e3bb90a/examples/views/docs/component/schema-form.md#">配置复用

因为与eagle-formeagle-form-item用法相同,所以除了可以用作表单以外,也可用作详情展示,同时因为本身是schema配置项,所以可以做到表单和详情配置复用

::: snippet 配置复用示例

<template>
  <el-row>
    <el-col :span="12">
      <div style="margin-bottom: 20px">表单</div>
      <eagle-schema-form v-model="form" :schema="schema"></eagle-schema-form>
    </el-col>
    <el-col :span="12">
      <div style="margin-bottom: 20px">详情</div>
      <eagle-schema-form :value="detail" :schema="detailSchema"></eagle-schema-form>
    </el-col>
  </el-row>
</template>

<script>
export default {
  data() {
    return {
      form: {
        name: '张三',
        age: 27,
        address: '上海市青浦区华新镇纪鹤公路1988号',
      },
      detail: {
        name: '张三',
        age: 27,
        address: '上海市青浦区华新镇纪鹤公路1988号',
      },
      schema: {
        props: { labelWidth: '70px', size: 'small', span: 12 },
        items: [
          { is: 'el-input', prop: 'name', label: '姓名' },
          { is: 'el-input-number', prop: 'age', label: '年龄' },
          { is: 'el-input', props: { type: 'textarea' }, prop: 'address', label: '住址', span: 24 },
        ]
      },
    };
  },
  computed: {
    detailSchema() {
      const schema = this.schema;
      // 去掉所有配置项的is参数即默认以文本展示
      return { ...schema, items: schema.items.map(({ is, ...other }) => ({ ...other })) }
    }
  }
};
</script>

:::

6a3e9fa03a9e62888fd3096196dcc68e3e3bb90a/examples/views/docs/component/schema-form.md#">自定义插槽

在某些特殊情况下,表单项可能是当前页面的临时组件,或者项目并没有全局引入组件,亦或者需要一些特殊的函数去处理,此时可以使用自定义插槽替换默认配置项。插槽默认提供了valueonInput用于维护当前值。

::: snippet schema配置中items配置项的is设置为slot,即可在组件下通过插槽的方式替换配置项。默认支持具名插槽label插槽、error插槽,与el-form-item的插槽类似。

<template>
  <eagle-schema-form v-model="form" :schema="schema">
    <!-- error插槽,作用:修改当前项的校验信息样式 -->
    <template #error-name>
      <div><span>请输入</span><el-tag size="mini">格式正确</el-tag><span>的姓名</span></div>
    </template>
    <!-- label插槽,作用:自定义当前项的label -->
    <template #label-age>
      <el-tooltip content="说明" placement="top" effect="light">
        <i class="el-icon-question"></i>
      </el-tooltip>
      <span>年龄</span>
    </template>
    <!-- 具名插槽,作用:自定义当前项的值 -->
    <template #address="{ value, onInput }">
      <div>
        <el-link size="mini" type="primary" :underline="false" @click="() => onInput('当前地址xxxxxx')">键入当前地址</el-link>
        <el-input type="textarea" :value="value" @input="onInput" />
      </div>
    </template>
  </eagle-schema-form>
</template>

<script>
export default {
  data() {
    return {
      form: {
        name: '张三',
        age: 27,
        address: '上海市青浦区华新镇纪鹤公路1988号',
      },
      schema: {
        props: { labelWidth: '70px', size: 'small', span: 12 },
        items: [
          { is: 'el-input', prop: 'name', label: '姓名', rules: [{ required: true, message: '请输入姓名' }] },
          { is: 'el-input-number', prop: 'age', label: '年龄' },
          { is: 'slot', prop: 'address', label: '住址', span: 24 },
        ]
      },
    };
  },
};
</script>

:::

6a3e9fa03a9e62888fd3096196dcc68e3e3bb90a/examples/views/docs/component/schema-form.md#">配置子节点

使用表单时,除了可能会出现单组件子节点以外,可能出现带有子节点的子组件。schema也支持对子节点进行配置。

::: snippet schema配置中items配置项的children可以配置子节点,格式同<component>组件。

<template>
  <eagle-schema-form v-model="form" :schema="schema"></eagle-schema-form>
</template>

<script>
export default {
  data() {
    return {
      form: {
        name: '张三',
        age: 27,
        address: '上海市青浦区华新镇纪鹤公路1988号',
        packages: ['零食'],
      },
      schema: {
        props: { labelWidth: '70px', size: 'small', span: 12 },
        items: [
          { is: 'el-input', prop: 'name', label: '姓名', rules: [{ required: true, message: '请输入姓名' }] },
          { is: 'el-input-number', prop: 'age', label: '年龄' },
          { is: 'el-input', props: { type: 'textarea' }, prop: 'address', label: '住址', span: 24 },
          {
            is: 'el-checkbox-group',
            prop: 'packages',
            label: '包裹',
            children: [
              { is: 'el-checkbox', props: { label: '零食' } },
              { is: 'el-checkbox', props: { label: '手机' } },
              { is: 'el-checkbox', props: { label: '电脑' } },
            ],
            span: 24
          },
        ]
      },
    };
  },
};
</script>

:::

6a3e9fa03a9e62888fd3096196dcc68e3e3bb90a/examples/views/docs/component/schema-form.md#">复杂表单

一般情况下,复杂表单建议使用eagle-formeagle-form-item等组件构建视图,不建议使用schema的方式配置。但是利用schema配置项的一些特性,也可以做到部分复杂表单使用schema配置完成。

::: snippet 包含了插槽子节点自定义子节点的复杂示例

<template>
  <eagle-schema-form v-model="form" :schema="schema" @submit="onSubmit" @cancel="onCancel">
    <template #error-name>
      <div><span>请输入</span><el-tag size="mini">格式正确</el-tag><span>的姓名</span></div>
    </template>
    <template #label-packages>
      <el-tooltip content="详情" placement="top" effect="light">
        <i class="el-icon-question"></i>
      </el-tooltip>
      <span>包裹</span>
    </template>
  </eagle-schema-form>
</template>

<script>
export default {
  data() {
    return {
      form: {
        name: '张三',
        age: 27,
        address: '上海市青浦区华新镇纪鹤公路1988号',
        packages: ['零食'],
        info: {
          mobile: '18888888888',
        },
        admin: 'false',
      },
      schema: {
        props: { labelWidth: '70px', size: 'small', span: 12 },
        items: [
          { is: 'el-input', prop: 'name', label: '姓名', rules: [{ required: true, message: '请输入姓名' }] },
          { is: 'el-input-number', prop: 'age', label: '年龄' },
          { is: 'el-input', prop: 'info.mobile', label: '电话' },
          { is: 'el-divider', props: { 'content-position': 'left' }, children: '收货信息', span: 24, labelWidth: '0px' },
          { is: 'el-input', props: { type: 'textarea' }, prop: 'address', label: '住址', span: 24 },
          {
            is: 'el-checkbox-group',
            prop: 'packages',
            label: '包裹',
            children: [
              { is: 'el-checkbox', props: { label: '零食' } },
              { is: 'el-checkbox', props: { label: '手机' } },
              { is: 'el-checkbox', props: { label: '电脑' } },
            ],
          },
          {
            is: 'el-select',
            prop: 'admin',
            label: '管理员',
            children: [
              {
                is: 'el-option',
                props: { label: '是', value: 'true' },
                children: [
                  {
                    is: 'div',
                    attrs: { style: 'display: flex; align-items: center; justify-content: space-between' },
                    children: [
                      { is: 'span', children: '是' },
                      { is: 'el-tag', props: { size: 'mini', type: 'success' }, children: 'yes' },
                    ]
                  },
                ]
              },
              {
                is: 'el-option',
                props: { label: '否', value: 'false' },
                children: [
                  {
                    is: 'div',
                    attrs: { style: 'display: flex; align-items: center; justify-content: space-between' },
                    children: [
                      { is: 'span', children: '否' },
                      { is: 'el-tag', props: { size: 'mini', type: 'warning' }, children: 'no' },
                    ]
                  },
                ]
              },
            ],
          },
        ]
      },
    };
  },
  methods: {
    onSubmit(value) {
      console.log(value);
    },
    onCancel() {
      console.log('cancal');
    }
  }
};
</script>

:::

API

Attribute 属性

参数|说明|类型|可选值|默认值 -|-|-|-|- value | 值 | Object | - | {} schema | JSON Schema配置项列表 | Object | - | {}

Events 事件

事件名称|说明|回调参数 -|-|- input | 表单值变化 | model