Skip to content

渲染时监听事件

FormCreate 支持将表单内部事件抛出到业务组件中,让您可以在业务组件代码中监听和处理这些事件的业务逻辑。这种方式实现了表单与业务逻辑的解耦,使表单更加灵活和可维护。

获取 API

在使用事件 API 之前,您需要先获取 API 对象。API 对象可以通过事件、验证函数、钩子函数等方式获取。

详细说明请查看:如何获取 API

抛出事件

在表单事件中,通过 api.emit() 方法可以抛出自定义事件,将事件传递到业务组件中。

避免与内置事件重名

请避免使用 FormCreate 的内置事件名称作为自定义事件名,否则可能会与内置事件冲突。

常见的内置事件包括:

  • submit - 表单提交事件
  • change - 表单数据变化事件
  • update:modelValue - 表单数据更新事件
  • mounted - 表单挂载完成事件
  • created - 表单创建完成事件
  • validateFail - 验证失败事件

建议:使用有意义的自定义事件名,如 formSubmitfieldChangedataLoaded 等,避免与内置事件冲突。

1. 在按钮点击事件中抛出事件

js
{
  type: 'button',
  field: 'submitBtn',
  title: '提交',
  on: {
    click: function($inject) {
      //确保获取到最外层表单的 API
      const api = $inject.api.top;

      // 获取表单数据
      const formData = api.formData();

      // 抛出提交事件,传递表单数据
      api.emit('formSubmit', formData);
    }
  }
}

2. 在字段变化时抛出事件

js
{
  type: 'input',
  field: 'username',
  title: '用户名',
  on: {
    change: function($inject) {
      //确保获取到最外层表单的 API
      const api = $inject.api.top;
      const value = $inject.args[0];

      // 抛出字段变化事件
      api.emit('fieldChange', {
        field: 'username',
        value: value
      });
    }
  }
}

通过标签方式监听

在渲染表单时,可以通过 Vue 的事件监听语法 @事件名 来监听表单抛出的事件,并在业务组件中处理业务逻辑。

1. 监听表单提交事件

vue
<template>
  <form-create 
    v-model="formData" 
    v-model:api="fApi"
    :rule="rule"
    @formSubmit="handleFormSubmit"
  />
</template>

<script setup>
import { ref } from 'vue';
import axios from 'axios';

const formData = ref({});
const fApi = ref(null);
const rule = ref([
  {
    type: 'button',
    field: 'submitBtn',
    title: '提交',
    on: {
      click: function($inject) {
        const api = $inject.api;
        api.emit('formSubmit', api.formData());
      }
    }
  }
]);

// 处理表单提交
async function handleFormSubmit(formData) {
  try {
    const response = await axios.post('/api/submit', formData);
    console.log('提交成功:', response.data);

    // 显示成功消息
    if (fApi.value && fApi.value.message) {
      fApi.value.message('提交成功', 'success');
    }
  } catch (error) {
    console.error('提交失败:', error);

    // 显示错误消息
    if (fApi.value && fApi.value.message) {
      fApi.value.message('提交失败', 'error');
    }
  }
}
</script>

2. 监听字段变化事件

vue
<template>
  <form-create 
    v-model="formData" 
    v-model:api="fApi"
    :rule="rule"
    @fieldChange="handleFieldChange"
  />
</template>

<script setup>
import { ref } from 'vue';

const formData = ref({});
const fApi = ref(null);
const rule = ref([
  {
    type: 'input',
    field: 'username',
    title: '用户名',
    on: {
      change: function($inject) {
        const api = $inject.api;
        api.emit('fieldChange', {
          field: 'username',
          value: $inject.args[0]
        });
      }
    }
  }
]);

// 处理字段变化
function handleFieldChange({ field, value }) {
  console.log(`字段 ${field} 变化为:`, value);

  // 根据字段变化执行业务逻辑
  if (field === 'username') {
    // 检查用户名是否可用
    checkUsernameAvailability(value);
  }
}

function checkUsernameAvailability(username) {
  // 业务逻辑:检查用户名是否可用
  console.log('检查用户名:', username);
}
</script>

3. 监听多个事件

vue
<template>
  <form-create 
    v-model="formData" 
    v-model:api="fApi"
    :rule="rule"
    @formSubmit="handleFormSubmit"
    @formValidate="handleFormValidate"
    @dataLoaded="handleDataLoaded"
    @dataLoadError="handleDataLoadError"
  />
</template>

<script setup>
import { ref } from 'vue';

const formData = ref({});
const fApi = ref(null);
const rule = ref([
  // 表单规则
]);

// 处理表单提交
function handleFormSubmit(formData) {
  console.log('表单提交:', formData);
  // 业务逻辑
}

// 处理表单验证
function handleFormValidate({ valid }) {
  console.log('验证结果:', valid);
  // 业务逻辑
}

// 处理数据加载完成
function handleDataLoaded({ field, data }) {
  console.log(`字段 ${field} 数据加载完成:`, data);
  // 业务逻辑
}

// 处理数据加载错误
function handleDataLoadError({ field, error }) {
  console.error(`字段 ${field} 数据加载失败:`, error);
  // 错误处理逻辑
}
</script>

通过API方式监听

在获取到 API 对象后,可以通过 api.bus.$on() 方法动态监听事件,这种方式更加灵活,可以在组件的任何生命周期中注册事件监听器。

vue
<template>
  <form-create 
    v-model="formData" 
    v-model:api="fApi"
    :rule="rule"
  />
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';

const formData = ref({});
const fApi = ref(null);
const rule = ref([
  {
    type: 'button',
    field: 'submitBtn',
    title: '提交',
    on: {
      click: function($inject) {
        $inject.api.emit('formSubmit', $inject.api.formData());
      }
    }
  }
]);

// 事件处理函数
function handleFormSubmit(formData) {
  console.log('表单提交:', formData);
  // 处理业务逻辑
}

// 组件挂载时注册监听
onMounted(() => {
  if (fApi.value) {
    fApi.value.on('formSubmit', handleFormSubmit);
  }
});

// 组件卸载前移除监听(可选)
onBeforeUnmount(() => {
  if (fApi.value) {
    fApi.value.off('formSubmit', handleFormSubmit);
  }
});
</script>

注意事项

重要提示

  1. 避免与内置事件重名请勿使用 FormCreate 的内置事件名称(如 submitchangeupdate:modelValuemountedcreated 等)作为自定义事件名,否则会与内置事件冲突,导致不可预期的行为
  2. 事件名称:事件名称是字符串,建议使用有意义的命名,如 formSubmitfieldChangedataLoaded 等,使用驼峰命名法
  3. 事件参数api.emit() 可以传递多个参数,这些参数会传递给事件处理函数
  4. 监听时机:使用 api.bus.$on() 时,确保 API 对象已经初始化,建议在 watchonMounted 中注册
  5. 内存泄漏:如果使用 api.bus.$on() 注册监听器,建议在组件卸载时使用 api.bus.$off() 移除监听器,避免内存泄漏
  6. 两种方式的选择
    • 模板事件监听:适合在组件模板中直接声明,代码更清晰,Vue 会自动处理清理
    • API 方法监听:适合动态注册和移除,更灵活,但需要手动管理