我今年主要做活动,会遇到很多预约报名的功能,一个页面,两个报名表单(内嵌在页面的表单和弹窗表单),其实两表单内容功能都是一样的,只是布局会有些不同,但是因为我们现在的项目并没有加入什么状态管理的模块,所以只能手动实现同步数据的功能。之前再遇到这种需求的时候因为时间问题,就写了两个表单组件分别管理自己的数据,但是这种解决方案真的是费力不讨好,稍微有些改动就要两个表单组件同时改,所以我就想了些优化方案:

补充:我主要主要是写在pc端同步表单的,如果在移动端的话,如果两表单内容一致,可直接使用一个表单组件,在弹窗时,让该表单组件固定定位,并使嵌入表单那一块元素固定高度就可以了

一.目标:

  一个表单组件,在同一页面中可在不同地方同时使用,并实现数据同步功能

二.解决方案:(前提:已写好表单组件,实例化该表单组件即表单对象)

  1.表单组件可直接作为内嵌表单,然后吧表单对象传给弹窗组件,在弹窗组件内渲染出来。

    结果:虽然功能实现了,但问题是页面中仅能同时渲染一个表单组件。不能同时显示,弃

  2.再实例化一个表单组件的对象,传递给弹窗组件,在弹窗组件中渲染,并维护这个新表单对象的数据。

    结果:2.1虽然功能实现了,但数据不能同步。因为其实是两个对象,所以对应的数据肯定是相互独立的,所以必须手动同步数据

       2.2手动同步数据其实只需要在打开和关闭弹窗时,判断两表单对象中的数据是否一只,然后对应更新表单对象数据并重新渲染即可

       2.3在弹窗表单中,常需要报名成功后关闭弹窗,因为在报名成功后需要修改整个页面中部分组件的状态,所以可以直接在修改状态时,关闭弹窗

三.总结:

  哈哈哈,使用解决方案二,最终试验成功。还是redux,vuex这些状态管理机制好用啊,直接就同步了,我们这个backbone项目基本上只是用了view层,后续在活动不忙的时候我试试看能否把其余的集成进来,就不用这么绕了。

四.关键代码:

import Form from './form'; // 表单组件
import FormDialog from './formDialog1'; // 弹窗组件
 
this.form = new Form({
  cityCode,
  signUpStatus,
  id,
  updateSignUpStatus: this._updateSignUpStatus // 报名成功后会修改页面状态
});
this.form1 = new Form({ // 嵌入页面的表单组件
  cityCode,
  signUpStatus,
  id,
  toggleShowSignSucess: this._toggleShowSignSucess, 
});
this.formDialog = new FormDialog({ 
  form: this.form1, // 将表单组件对象放入弹窗组件中
  syncFormData: this._syncFormData // 用户关闭弹窗时同步嵌入表单组件数据
});
// 修改页面报名状态
updateSignUpStatus(signUpStatus) {
  Object.assign(this.options, { signUpStatus });
  if (signUpStatus) {
    // 隐藏表单弹窗
    if (this.formDialog.options.show) this.formDialog.toggleShow();
    // 更新两表单改变状态
    this.form.update({ signUpStatus });
    this.form1.update({ signUpStatus });
  }
}
// 同步表单数据
syncFormData(show) {
  if (!show) { // 打开弹窗,同步弹窗表单数据
    if (JSON.stringify(this.form.options) !== JSON.stringify(this.form1.options)) {
      this.form1.update(this.form.options);
    }
  } else { // 关闭弹窗,同步嵌入表单数据
    if (JSON.stringify(this.form.options) !== JSON.stringify(this.form1.options)) {
      this.form.update(this.form1.options);
    }
  }
}
// 渲染方法
render() {
  this.$el.find('.form-contianer').html(this.form.render()); //嵌入表单组件放入页面
  this.$el.find('.formDialog-container').html(this.formDialog.render());//弹窗表单组件放入页面
}