Select 
下拉框组件
Markup Schema 同步数据源案例 
*
:请选择
vue
<template>
  <FormProvider :form="form">
    <SchemaField>
      <SchemaStringField
        required
        name="select"
        title="选择框"
        x-decorator="FormItem"
        x-component="Select"
        :x-component-props="{
          style: {
            width: '240px',
          },
          clearable: true,
          onChange: (e) => {
            console.log('change')
          },
        }"
        :enum="[
          {
            label: '选项1',
            value: 1,
          },
          {
            label: '选项2',
            value: 2,
          },
        ]"
      />
    </SchemaField>
    <Submit @submit="log">提交</Submit>
  </FormProvider>
</template>
<script>
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/vue'
import { Formily } from 'element-plus-x'
const { FormItem, Select, Submit } = Formily
const form = createForm()
const fields = createSchemaField({
  components: {
    FormItem,
    Select,
  },
})
export default {
  components: { FormProvider, ...fields, Submit },
  data() {
    return {
      form,
    }
  },
  methods: {
    log(value) {
      console.log(value)
    },
  },
}
</script>
隐藏源代码
Markup Schema 异步搜索案例 
:
请选择
vue
<template>
  <FormProvider :form="form">
    <SchemaField>
      <SchemaStringField
        name="select"
        title="异步搜索选择框"
        x-decorator="FormItem"
        x-component="Select"
        :x-component-props="{
          filterable: true,
          remote: true,
          style: {
            width: '240px',
          },
        }"
      />
    </SchemaField>
    <Submit @submit="log">提交</Submit>
  </FormProvider>
</template>
<script>
import { createForm, onFieldInit, onFieldReact } from '@formily/core'
import { action, observable } from '@formily/reactive'
import { FormProvider, createSchemaField } from '@formily/vue'
import { Formily } from 'element-plus-x'
const { FormItem, Select, Submit } = Formily
let timeout
let currentValue
function fetchData(value, callback) {
  if (timeout) {
    clearTimeout(timeout)
    timeout = null
  }
  currentValue = value
  function fake() {
    callback([
      {
        label: 'AAA',
        value: 'aaa',
      },
      {
        label: 'BBB',
        value: 'ccc',
      },
    ])
  }
  timeout = setTimeout(fake, 300)
}
const useAsyncDataSource = (pattern, service) => {
  const keyword = observable.ref('')
  onFieldInit(pattern, (field) => {
    field.setComponentProps({
      remoteMethod: (value) => {
        keyword.value = value
      },
    })
  })
  onFieldReact(pattern, (field) => {
    field.loading = true
    service({ field, keyword: keyword.value }).then(
      action.bound((data) => {
        field.dataSource = data
        field.loading = false
      })
    )
  })
}
const form = createForm({
  effects: () => {
    useAsyncDataSource('select', async ({ keyword }) => {
      if (!keyword) {
        return []
      }
      return new Promise((resolve) => {
        fetchData(keyword, resolve)
      })
    })
  },
})
const fields = createSchemaField({
  components: {
    FormItem,
    Select,
  },
})
export default {
  components: { FormProvider, ...fields, Submit },
  data() {
    return {
      form,
    }
  },
  methods: {
    log(value) {
      console.log(value)
    },
  },
}
</script>
隐藏源代码
Markup Schema 异步搜索案例 
组件属性remoteMethod的写法
:
请选择
vue
<template>
  <FormProvider :form="form">
    <SchemaField>
      <SchemaStringField
        name="select"
        title="异步搜索选择框"
        x-decorator="FormItem"
        x-component="Select"
        :x-component-props="{
          filterable: true,
          remote: true,
          remoteMethod: remoteMethod,
          style: {
            width: '240px',
          },
        }"
      />
    </SchemaField>
    <Submit @submit="log">提交</Submit>
  </FormProvider>
</template>
<script setup lang="ts">
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/vue'
import { Formily } from 'element-plus-x'
import type { Field } from '@formily/core'
const { FormItem, Select, Submit } = Formily
const states = [
  '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 list = states.map((item) => {
  return { value: `value:${item}`, label: `label:${item}` }
})
let tick: any
const remoteMethod = (query: string) => {
  const field = form.query('*').take() as Field
  if (query) {
    clearTimeout(tick)
    field.loading = true
    tick = setTimeout(() => {
      if (field) {
        field.setDataSource(
          list.filter((item) => {
            return item.label.toLowerCase().includes(query.toLowerCase())
          })
        )
        field.loading = false
      }
    }, 200)
  } else {
    if (field) {
      field.setDataSource([])
    }
  }
}
const form = createForm({})
const fields = createSchemaField({
  components: {
    FormItem,
    Select,
  },
})
const { SchemaField, SchemaStringField } = fields
const log = (value: Record<string, any>) => {
  console.log(value)
}
</script>
隐藏源代码
Markup Schema 异步联动数据源案例 
vue
<template>
  <Form :form="form">
    <SchemaField>
      <SchemaNumberField
        name="linkage"
        title="联动选择框"
        x-decorator="FormItem"
        x-component="Select"
        :enum="[
          { label: '发请求1', value: 1 },
          { label: '发请求2', value: 2 },
        ]"
        :x-component-props="{
          style: {
            width: '240px',
          },
        }"
      />
      <SchemaStringField
        name="select"
        title="异步选择框"
        x-decorator="FormItem"
        x-component="Select"
        :x-component-props="{
          style: {
            width: '240px',
          },
        }"
      />
    </SchemaField>
    <Submit @submit="onSubmit">提交</Submit>
  </Form>
</template>
<script>
import { createForm, onFieldReact } from '@formily/core'
import { createSchemaField } from '@formily/vue'
import { action } from '@formily/reactive'
import { Formily } from 'element-plus-x'
const { Form, FormItem, Select, Submit } = Formily
const useAsyncDataSource = (pattern, service) => {
  onFieldReact(pattern, (field) => {
    field.loading = true
    service(field).then(
      action.bound((data) => {
        field.dataSource = data
        field.loading = false
      })
    )
  })
}
const form = createForm({
  effects: () => {
    useAsyncDataSource('select', async (field) => {
      const linkage = field.query('linkage').get('value')
      if (!linkage) return []
      field.query('select').take().setValue('')
      return new Promise((resolve) => {
        setTimeout(() => {
          if (linkage === 1) {
            resolve([
              {
                label: 'AAA',
                value: 'aaa',
              },
              {
                label: 'BBB',
                value: 'ccc',
              },
            ])
          } else if (linkage === 2) {
            resolve([
              {
                label: 'CCC',
                value: 'ccc',
              },
              {
                label: 'DDD',
                value: 'ddd',
              },
            ])
          }
        }, 1500)
      })
    })
  },
})
const fields = createSchemaField({
  components: {
    FormItem,
    Select,
  },
})
export default {
  components: { Form, ...fields, Submit },
  data() {
    return {
      form,
    }
  },
  methods: {
    onSubmit(value) {
      console.log(value)
    },
  },
}
</script>
隐藏源代码
Markup Schema 插槽案例 
如果你想拿到插槽作用域属性值,render函数必须至少有 2 个参数,这是受 ReactiveField组件 merge slots 的实现所约束
ts
const resolveComponent = (render: () => unknown[], extra?: any) => {
  // ...
  // for scoped slot
  if (extra.length > 1 || extra?.render?.length > 1) {
    return (scopedProps: VueComponentProps<any>) => [
      ...render(),
      h(extra, { props: scopedProps }, {}),
    ]
  }
  // ...
}支持 el-select 所有插槽,el-option 的默认插槽改成了 option 插槽(因为 el-select 也有默认插槽)
:
请选择
vue
<template>
  <FormProvider :form="form">
    <SchemaField>
      <SchemaStringField
        name="select"
        title="选择框"
        x-decorator="FormItem"
        x-component="Select"
        :x-component-props="{
          style: {
            width: '240px',
          },
        }"
        :enum="[
          {
            label: '选项1',
            value: 1,
          },
          {
            label: '选项2',
            value: 2,
          },
        ]"
        :x-content="content"
      />
    </SchemaField>
    <Submit @submit="log">提交</Submit>
  </FormProvider>
</template>
<script setup>
import { h } from 'vue'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/vue'
import { Formily } from 'element-plus-x'
const { FormItem, Select, Submit } = Formily
const form = createForm()
const fields = createSchemaField({
  components: {
    FormItem,
    Select,
  },
})
const { SchemaField, SchemaStringField } = fields
const log = (value) => {
  console.log(value)
}
const content = {
  // option为 el-option 组件的默认插槽
  option: {
    props: ['option'],
    render(thisProxy, proxyToUse) {
      const { option } = thisProxy
      return h('div', {}, `${option.label}-${option.value}`)
    },
  },
  header: {
    render() {
      return h('div', {}, `header`)
    },
  },
}
</script>
隐藏源代码
JSON Schema 同步数据源案例 
vue
<template>
  <Form :form="form">
    <SchemaField :schema="schema" />
    <Submit @submit="onSubmit">提交</Submit>
  </Form>
</template>
<script>
import { createForm } from '@formily/core'
import { createSchemaField } from '@formily/vue'
import { Formily } from 'element-plus-x'
const { Form, FormItem, Select, Submit } = Formily
const schema = {
  type: 'object',
  properties: {
    select: {
      type: 'string',
      title: '选择框',
      enum: [
        {
          label: '选项1',
          value: 1,
        },
        {
          label: '选项2',
          value: 2,
        },
      ],
      'x-decorator': 'FormItem',
      'x-component': 'Select',
      'x-component-props': {
        style: 'width: 240px;',
        clearable: true,
      },
    },
  },
}
const form = createForm()
const { SchemaField } = createSchemaField({
  components: {
    FormItem,
    Select,
  },
})
export default {
  components: { Form, SchemaField, Submit },
  data() {
    return {
      form,
      schema,
    }
  },
  methods: {
    onSubmit(value) {
      console.log(value)
    },
  },
}
</script>
隐藏源代码
JSON Schema 异步联动数据源案例 
vue
<template>
  <Form :form="form">
    <SchemaField :schema="schema" :scope="{ useAsyncDataSource, loadData }" />
    <Submit @submit="onSubmit">提交</Submit>
  </Form>
</template>
<script>
import { createForm } from '@formily/core'
import { createSchemaField } from '@formily/vue'
import { action } from '@formily/reactive'
import { Formily } from 'element-plus-x'
const { Form, FormItem, Select, Submit } = Formily
const schema = {
  type: 'object',
  properties: {
    linkage: {
      type: 'string',
      title: '联动选择框',
      enum: [
        {
          label: '发请求1',
          value: 1,
        },
        {
          label: '发请求2',
          value: 2,
        },
      ],
      'x-decorator': 'FormItem',
      'x-component': 'Select',
      'x-component-props': {
        style: 'width: 240px;',
      },
    },
    select: {
      type: 'string',
      title: '异步选择框',
      'x-decorator': 'FormItem',
      'x-component': 'Select',
      'x-component-props': {
        style: 'width: 240px;',
      },
      'x-reactions': ['{{useAsyncDataSource(loadData)}}'],
    },
  },
}
const useAsyncDataSource = (service) => (field) => {
  field.loading = true
  service(field).then(
    action.bound((data) => {
      field.dataSource = data
      field.loading = false
    })
  )
}
const loadData = async (field) => {
  const linkage = field.query('linkage').get('value')
  if (!linkage) return []
  return new Promise((resolve) => {
    setTimeout(() => {
      if (linkage === 1) {
        resolve([
          {
            label: 'AAA',
            value: 'aaa',
          },
          {
            label: 'BBB',
            value: 'ccc',
          },
        ])
      } else if (linkage === 2) {
        resolve([
          {
            label: 'CCC',
            value: 'ccc',
          },
          {
            label: 'DDD',
            value: 'ddd',
          },
        ])
      }
    }, 1500)
  })
}
const form = createForm()
const { SchemaField } = createSchemaField({
  components: {
    FormItem,
    Select,
  },
})
export default {
  components: { Form, SchemaField, Submit },
  data() {
    return {
      form,
      schema,
    }
  },
  methods: {
    useAsyncDataSource,
    loadData,
    onSubmit(value) {
      console.log(value)
    },
  },
}
</script>
隐藏源代码
Template 同步数据源案例 
:
请选择
vue
<template>
  <FormProvider :form="form">
    <Field
      name="select"
      title="选择框"
      :decorator="[FormItem]"
      :component="[
        Select,
        {
          style: {
            width: '240px',
          },
          clearable: true,
        },
      ]"
      :data-source="[
        {
          label: '选项1',
          value: 1,
        },
        {
          label: '选项2',
          value: 2,
        },
      ]"
    />
    <Submit @submit="log">提交</Submit>
  </FormProvider>
</template>
<script>
import { createForm } from '@formily/core'
import { Field, FormProvider } from '@formily/vue'
import { Formily } from 'element-plus-x'
const { FormItem, Select, Submit } = Formily
const form = createForm()
export default {
  components: { FormProvider, Field, Submit },
  data() {
    return {
      FormItem,
      Select,
      form,
    }
  },
  methods: {
    log(value) {
      console.log(value)
    },
  },
}
</script>
隐藏源代码
Template 异步联动数据源案例 
vue
<template>
  <Form :form="form">
    <Field
      name="linkage"
      title="联动选择框"
      :decorator="[FormItem]"
      :component="[
        Select,
        {
          style: {
            width: '240px',
          },
        },
      ]"
      :data-source="[
        { label: '发请求1', value: 1 },
        { label: '发请求2', value: 2 },
      ]"
    />
    <Field
      name="select"
      title="异步选择框"
      :decorator="[FormItem]"
      :component="[
        Select,
        {
          style: {
            width: '240px',
          },
        },
      ]"
    />
    <Submit @submit="onSubmit">提交</Submit>
  </Form>
</template>
<script>
import { createForm, onFieldReact } from '@formily/core'
import { Field } from '@formily/vue'
import { action } from '@formily/reactive'
import { Formily } from 'element-plus-x'
const { Form, FormItem, Select, Submit } = Formily
const useAsyncDataSource = (pattern, service) => {
  onFieldReact(pattern, (field) => {
    field.loading = true
    service(field).then(
      action.bound((data) => {
        field.dataSource = data
        field.loading = false
      })
    )
  })
}
const form = createForm({
  effects: () => {
    useAsyncDataSource('select', async (field) => {
      const linkage = field.query('linkage').get('value')
      if (!linkage) return []
      return new Promise((resolve) => {
        setTimeout(() => {
          if (linkage === 1) {
            resolve([
              {
                label: 'AAA',
                value: 'aaa',
              },
              {
                label: 'BBB',
                value: 'ccc',
              },
            ])
          } else if (linkage === 2) {
            resolve([
              {
                label: 'CCC',
                value: 'ccc',
              },
              {
                label: 'DDD',
                value: 'ddd',
              },
            ])
          }
        }, 1500)
      })
    })
  },
})
export default {
  components: { Form, Field, Submit },
  data() {
    return {
      form,
      FormItem,
      Select,
    }
  },
  methods: {
    onSubmit(value) {
      console.log(value)
    },
  },
}
</script>
隐藏源代码
API 
参考 ElSelect