element ui 表单模板_Vue 面向对象编程 - 综合运用 - 表单

本文探讨如何使用Vue的面向对象编程(OOP)方法,结合Element UI,优化表单组件的创建。通过抽象类,实现了FormItem和Form之间的智能双向绑定与模型导出。详细介绍了FormItem如何根据传入参数动态修改Form属性,并自动为子组件绑定,同时Form具备对FormItem的全面控制能力,降低了使用者的复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

b805722e973c20a68a48b3c584d3435a.png

之前的例子简单地说明了以下面向对象在 Vue 中的应用

很多人有不同意见,原因很简单,clipboard 返回的是单层对象,其实这种服务用原型也可以:

function ClipboardService(){
   return {
     initialContent :ref('')
     copyRef: ref<any>(null)
     // ...
   }
}

单层对象不会对类型声明造成太多影响,原型模式也是设计模式的一种,因此这种写法应对这种问题我也是支持的

但是接下来要讲的问题,不用面向对象,复杂度是直线上升的,我搞出这个来只用了20分钟左右,大家可以试试不用面向对象,在ts环境下需要多少时间


大家都用惯了 element-ui 了是么?

element-ui 有个表单组件:

// 模板中
<el-form ref="form" :model="form" label-width="80px">
  <el-form-item label="活动名称">
    <el-input v-model="form.name"></el-input>
  </el-form-item>
</el-form>

// 组件逻辑中(强烈反对组件中有逻辑)
data() {
      return {
        form: {
          name: ''
        }
      }
}

同样一个数据实体,在表单中绑定了太多次了

我们今天来看看新的 api 下,Vue 能够办到什么样的用法?

5697e056da9865a14c466a7d4e147c5c.png

还是 script 优先的写法,原因见之前的文章

所有逻辑,交给组件,你别瞎忙活

你的组件内部,无逻辑

能否实现双向绑定和 model 导出呢?

31d41810257468809740c70ec6849fee.png

可以的,怎么配合 面向对象 + SOA 实现呢?


这个问题比之前的 clipboard 要复杂,可能出现嵌套结构,之前的问题可以采用原型对象,这个问题不行,直接上极限面向对象

React 的话,推荐 useReducer,invoker 本身就是函数式模拟部分面向对象概念集成的东西,我反对的是全局统一命令模式跨平台,不反对 invoker state monad
但是 Vue 强烈反对用 vuex 或者相关技术 pania 之类,没有不变性约束,你用这个真的会炸

首先介绍给大家的是

抽象类

大家自行百度哈,网上相关解释太多了,编程界工程技术占100,面向对象独占 80

当然,抽象类现在收到了批判,很多人建议用 接口定义,抽象非具体,组合非继承,不过那都是后话,至少就这个问题的复杂度而言,我们先一步一步来

分析问题(想清楚是面向对象的第一要务,他只是翻译你心里的概念而已)

  • 我们需要 FormItem, 也需要 Form
  • FormItem 能自动绑定最近的 Form,但是如果有传入 Form 令牌,就绑定那个 Form 所在的令牌
  • FormItem 可以通过自己的参数,修改 Form 的属性,比如 item 实例,model 等
  • FormItem 需要自动为子组件加上绑定,这样可以让使用者负担最小化
  • Form 需要对其下的 FormItem 有全权控制能力

可以,两个抽象类,Form:

/**
 * abstract form
 *
 * @export
 * @abstract
 * @class Form
 */
export abstract class Form {
  items: Ref<{ [key: string]: FormItem | null }> = ref({});

  /**
   * uno layer form value
   *
   * @type {Ref<{ [key: string]: any }>}
   * @memberof Form
   */
  value: Ref<{ [key: string]: any }> = ref({});
  keys: Ref<string[]> = ref([]);
  errors: Ref<string[]> = ref([]);
  rules: Ref<{ [key: string]: Rule[] }> = ref({});
  layout: Ref<FORM_LAYOUT_OPTIONS> = ref(FORM_LAYOUT_OPTIONS.vertical);
  token: string;

  /**
   * Creates an instance of Form.
   * binding withe the props of component
   * @param FormProps props
   * @memberof Form
   */
  constructor(props: FormProps) {
    this.value.value = props.initialValue || {};
    this.keys.value = props.initialValue ? Object.keys(props.initialValue) : [];
    this.rules.value = props.rules || {};
    this.layout.value = props.layout || FORM_LAYOUT_OPTIONS.vertical;
    this.token = props.token || "form-" + ~~(Math.random() * 1000);
  }

  // TODO: 控制器还没想好
}

Form Item 抽象类:

/**
 * abstract formitem
 *
 * @export
 * @abstract
 * @class FormItem
 */
export abstract class FormItem {
  /**
   * cannot change once initialized
   *
   * @type {string}
   * @memberof FormItem
   */
  name: string;
  label: Ref<string> = ref("");
  hasError: Ref<Boolean> = ref(false);
  errorString: Ref<string> = ref("");
  rules: Ref<Rule[]> = ref([]);
  token: symbol | InjectionKey<Form>;
  initialValue: any;

  /**
   * the form instance
   *
   * @type {Form}
   * @memberof FormItem
   */
  form: Form;

  constructor(props: FormItemProps) {
    this.name = props.name;
    this.label.value = props.label || "";
    this.rules.value = props.rules || [];
    this.form = inject(props.token || FormService.formToken);
    console.log(this.form);
    this.initialValue = props.initialValue;
  }

  /**
   * bind current instance with form
   *
   * @abstract
   * @memberof FormItem
   */
  abstract bindingForm(): void;
}

好了,接下来考虑各种问题实现真正的 FormService 和 FormItemService

4ac502cf61766b28f6b616a8b5292865.png

989b50421e878fd88547dcee7f538c95.png

最后 Form.vue 和 Formitem.vue

1015734c81f0bae49c162b8664f65910.png

1ba28739fc3dc9bf996a563a0446a181.png

以上

https://codesandbox.io/s/magical-black-6duy6​codesandbox.io
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值