Vue3 二次封装 Element Plus Form 组件的疑问,请求大家帮忙。

2021-11-16 10:46:21 +08:00
 17681880207

原因是这样的,因为项目中需要频繁的使用 form 表单,劳动力感觉非常重复,就决定还是对 element-plus 的 form 组件进行二次封装,尽量的做到配置化的开发。其中在开发 select 的 remote 模式的时候遇到了一些问题,自己调试了很久也没有找到解决办法。代码如下:

代码块 1 为二次封装的组件。核心思路就是根据 formItem 中的 type 字段,渲染不同类型的表单组件。

// 仅展示有问题的核心逻辑
<template>
  <el-form class="table-search-form"
           :model="props.model"
           :rules="props.rules">
    <el-row :gutter="32">
      <el-col
          v-for="(formItem, index) in props.formItems"
          :key="index"
          :span="formItem.span ? formItem.span : 6">
        <el-form-item
            :label="formItem.label"
            :prop="formItem.prop">
          <-- 隐藏其他类型 -->
          <el-select
              v-if="formItem.type === FORM_ITEM_TYPES.REMOTE_SELECT"
              v-model="props.model[formItem.prop]"
              :placeholder="formItem.placeholder ? formItem.placeholder : formItem.label"
              clearable
              filterable
              remote
              :remote-method="formItem.remoteMethod"
              style="width: 100%;">
            <el-option
                v-for="(option, index) in formItem.options"
                :key="index"
                :label="option.label"
                :value="option.value"/>
          </el-select>
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>

<script lang="ts" setup>
import {defineProps} from 'vue'

enum FORM_ITEM_TYPES {
  INPUT = 'input',
  SELECT = 'select',
  REMOTE_SELECT = 'remoteSelect'
}

const props = defineProps({
  formItems: {
    type: Array,
    default: () => []
  },
  model: {
    type: Object,
    default: () => ({})
  },
  rules: {
    type: Object,
    default: () => ({})
  }
})
</script>

代码块 2 为使用模块。

<template>
    <table-search-form
        :form-items="formItems"
        :model="model"
        :rules="rules"/>
</template>

<script lang="ts" setup>
import {reactive, ref} from 'vue'
import TableSearchForm from '@/components/TableSearchForm/index.vue'

const roles = ref<any[]>([
  {label: 'Role 1', value: 1}
])

const handleRemoteMethod = (query: string) => {
  setTimeout(() => {
    roles.value = [
      {label: 'Role 2', value: 2},
      {label: 'Role 3', value: 3}
    ]
    // 打印点 1
    console.log(roles.value)
  }, 1000)
}

const formItems = [
  // ...省略
  {
    label: '角色 ID',
    prop: 'roleId',
    type: 'remoteSelect',
    remoteMethod: handleRemoteMethod,
    options: roles.value
  }
]

const model = reactive({
  username: '张三',
  gender: 0,
  roleId: ''
})

const rules = {
  username: [{required: true, message: '用户名未输入。', trigger: 'none'}]
}
</script>

问题

因为是 remote 模式的 select ,所以我会传入一个 handleRemoteMethod 函数,动态修改它的 options ,这里的 options 用了一个 ref 进行接受然后传递到组件内部。但是当我发现触发 handleRemoteMethod 之后,打印出来的值(即:打印点 1 )已经修改了,但是组件渲染依旧只有 “Role 1” 这 1 个选项。但是我使用 roles.value.push(...[]) 的方法,可以正常的改变其渲染。 请问各位大佬,这是为啥?我应该如何做,求答疑解惑。

871 次点击
所在节点    问与答
2 条回复
17681880207
2021-11-16 11:26:39 +08:00
// 我将其中的代码,修改为如下,发现可以修改 options 了。
// 整个 formItems 加上 ref ,哪步的 roles 取消 .value 。
// 但是还是不是很清楚其中的缘由,有大佬可以帮忙分析一下吗?
const formItems = ref([
// ...省略
{
label: '角色 ID',
prop: 'roleId',
type: 'remoteSelect',
remoteMethod: handleRemoteMethod,
options: roles
}
])
4ark
2021-11-16 20:46:31 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/815706

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX