Vue3依赖注入的简单实践及封装Form表单的浅层思考

386 阅读2分钟

最近又在搭前端基础框架,被告知不能用我心心念念的React,其实还是有点难过的,毕竟react已经写了好久了,突然不用了还有点舍不得。既然不能用React,那就用Vue3 + Element-plus来cv吧
对于项目的搭建,前期要做的事有很多。 比如 封装一个简单易用的Form表单。
由于vue是双向数据绑定, 我们不需要像antdform表单那样去设计,直接将存放数据的objectform进行绑定即可
这里我们用到了vue3依赖注入
2022.10.9 更新,完善了异步的依赖注入

这里我简单的画了一个脑图

截屏2022-09-26 11.48.42.png

Form组件

<script setup lang="ts">
import { reactive, inject, ref, computed } from 'vue';
const props = withDefaults(defineProps<{
    data: object,
    editable?: boolean
}>(), {
    editable: false
})

/**
 *  这里提供form需要绑定的object,以便 form内的input可以获取到进行数据绑定
 *  这里使用了计算属性,当异步获取数据时,provide不能及时的将数据提供,所以在这里要进行处理
 */
provide('data', computed(() => props.form))
provide('editable', readonly(props.editable))
</script>
<template>
    <el-form ref="formRef"  :model="props.data" :scroll-to-error="true">
        <el-row justify="space-between" class="form-row" :gutter="24">
            <slot class="form-inputs"></slot>
        </el-row>
    </el-form>
</template>

Input组件

<script setup lang="ts">
import { reactive, inject, ref } from 'vue';
type formObject = { [key: string]: any }

const props = withDefaults(defineProps<{
    label: string,
    name: string,
    placeholder: string,
    editable?: boolean
}>(), {
    placeholder: '请输入',
    editable: undefined
})

let formEditable = inject('editable')

let defaultEditable: { flag: boolean } = reactive({
    flag: true
})

/**
 * 模拟Form和 Form标签包裹组件的权重 comp > form
 * 不懂的可以看下面的文字
 */
if (props.editable === undefined) {
    defaultEditable.flag = formEditable as boolean
} else {
    defaultEditable.flag = props.editable as boolean
}

</script>
<template>
    <el-form-item :label="props.label" :prop="props.name" label-width="150px">
        <el-input class="text-input" v-if="defaultEditable.flag" v-model="data[(name) as string]"
            :placeholder="props.placeholder" />
        <span v-else>{{ data[(name) as string] ?? '暂无数据' }}</span>
    </el-form-item>
</template>

来自小开发的思考

众所周知, 后台管理一般都是一个详情页面,既承担了新增/编辑功能,又承担了查看详情的功能,我们只需要根据分页点击不同的按钮(新增/编辑/查看详情),传入对应的flag,就可以让一个页面承担起多个业务功能。
通常来讲,我们往往希望被Form表单包裹的一些组件,可以根据一些字段自动地处理自身的状态,例如:
新增时,我们希望页面长这个样子:

截屏2022-09-26 15.14.37.png

编辑时,我们希望页面长这个样子:(日期字段变成不可输入状态)

截屏2022-09-26 15.18.29.png 查看详情时,我们希望页面又是一个样子:

截屏2022-09-26 15.19.44.png 所以,这就需要我们对一些字段进行一些处理(其实就是给一个默认值)
我们希望的是,写更少的代码做更多的事情。所以,我们需要先行处理editable这个字段。

  1. 我们先将传入Inputeditable属性默认值设置为undefined
    const props = withDefaults(defineProps<{
        label: string,
        name: string,
        placeholder: string,
        editable?: boolean,
    }>(), {
        placeholder: '请输入',
        // 🙋‍♂️
        editable: undefined
    })
    
  2. 然后我们进行判断,如果editable === undefined就代表我在调用Input组件时,没有对editable赋值,此时,可以使用Form提供的editable来控制当前是可输入状态还是仅展示文字状态
      // 🙋 
      if (props.editable === undefined) {
           defaultEditable.flag = formEditable as boolean
       } else {
           defaultEditable.flag = props.editable as boolean
       }

使用

<script setup lang="ts">
const formObjectData = reactive({
    name: '张三',
    age: 12,
})
</script>
<template>
        <Form :form="formObjectData" :editable="false">
            <Input label="姓名" name="name"/>
            <Input label="年龄" name="age" :editable="true"/>
        </Form>
</template>

截屏2022-09-26 15.30.42.png 肥肠好用