博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于Vue构造器创建Form组件的通用解决方案
阅读量:6623 次
发布时间:2019-06-25

本文共 4260 字,大约阅读时间需要 14 分钟。

在前端平常的业务中,无论是官网、展示页还是后台运营系统都离不开表单,它承载了大部分的数据采集工作。所以如何更好地实现它,是平常工作中的一个重要问题。

在应用Vue框架去开发业务时,会将页面上每个独立的可视/可交互区域拆分为一个组件,再通过多个组件的自由组合来组成新的页面。例如

复制代码

当用户的某个行为触发表单时(例如注册、建立内容等),期望在页面中弹出一个From组件。通常的做法是在template中填入一个<form>组件用于开发,并通过控制data中的UI.isOpen来对其display进行控制,例如在当前<template>组件内开发<register-form>

复制代码

这样开发有一点优势,Form组件与其父组件之间可以通过prop以及$emit方便通信。但是也会有以下几个缺陷:

  • 当前组件的data必须要有UI.isOpen来控制表单,如果存在多个表单时,就会有大量的状态来维护表单的开关;
  • 如果表单多次弹出时,可能需要对表单的data进行重置;
  • 与组件化思想相违背,表单不属于当前页面,它只是由于用户行为触发的结果。

为了解决以上缺陷,并且还能具备方便通信的优势,本文选择用Vue.extend将原有<form>组件转化为method function,并维护在当前组件的method中,当用户触发时,在页面中挂载,关闭时自动注销。

实例

演示地址:

代码地址:

  • APP组件
复制代码

<el-button>的点击事件触发时,调用register方法,将表单组件挂载在页面中。

  • Form组件
复制代码

在APP组件内并未维护<form>组件的状态,其打开或关闭只维护在自身的data中。

原理

上述代码中,最为关键的一步就是transform函数,它将原有的`

single-file components转化为了
method function,其原理如下

const transform = (component) => {  const _constructor = Vue.extend(component)  return function (options = {}) {    const {      propsData    } = options    let instance = new _constructor({      propsData    }).$mount(document.createElement('div'))    return instance  }}复制代码

首先利用创建一个<Form/>组件的子类

const _constructor = Vue.extend(component)复制代码

然后return function,它的功能是:

  • <form />组件转化为method
  • method调用时,将组件实例化并传递propsData
const {  propsData} = optionslet instance = new _constructor({  propsData}).$mount(document.createElement('div'))复制代码

为了能够控制实例化后的组件,选择instance返回。

当组件实例化时,它只是挂载到document.createElement('div')上,但是并没有挂载到页面上,所以需要将其appendChild到页面中。为了更好的语义化,选择在组件的生命周期中完成它在页面中的挂载。实例化时,会触发组件mounted生命周期,所以当其触发时可以挂载在document.body中,具体如下

mounted () {  document.body.appendChild(this.$el)}复制代码

有了挂载,就必须要有注销。对应的生命周期应该是destroyed,所以

method: {  destroyElement () {    this.$destroy()  }   },destroyed () {  this.$el.parentNode.removeChild(this.$el)}复制代码

组件注销的时间与它在页面中显示息息相关,当<form />在页面中不可见时候,需要注销它

watch: {  isVisible (newValue) {    if (!newValue) {      this.destroyElement()      // 如果需要添加过渡动画      // this.$el.addEventListener('transitionend', this.destroyElement)    }  }}复制代码

一般Form组件有两个功能:

  • done:代表用户确认;
  • cancel:代表用户取消;

当done或cancel触发时,APP组件内可能会有相应的变化,所以在组件实例化之后,利用$on去监听对应的done事件以及cancel事件。

done && inlineListen({  method: 'done',  options,  instance})cancel && inlineListen({  method: 'cancel',  options,  instance})复制代码

其中inlineListen函数可以方便后续添加其他的event,其代码为

const inlineListen = ({  method,  options,  instance}) => {  let listener = `on${method}`  instance[listener] = options[method]  instance.$on(method, function (data) {    this[listener](data)  })}复制代码

也可以将上述方案封装成Promise形式,如下

export const transform = (component) => {  const _constructor = Vue.extend(component)  return function (options = {}) {    const {      propsData    } = options    return new Promise((resolve, reject) => {      let instance = new _constructor({        propsData      }).$mount(document.createElement('div'))      instance.$on('done', data => resolve(data))    })  }}复制代码

使用

可以将上述属于<Form/>公有的data以及method独立出来,再通过mixins引入到每个表单内,例如

export default {  data() {    return {      visible: true    }  },  watch: {    visible(newValue) {      if (!newValue) {        this.destroyElement()      }    }  },  mounted() {    document.body.appendChild(this.$el)  },  destroyed() {    this.$el.parentNode.removeChild(this.$el)  },  methods: {    destroyElement() {      this.$destroy()    },    close() {      this.visible = false    }  }}复制代码

再通过mixins混入。

复制代码

调用时,只需

export default {  name: 'App',  methods: {    register: transform(register),    handleClick () {      this.register({        propsData: {          ...        },        // done: data => function        done () {            // 外部关闭            this.close()        }      })    }  }}复制代码

PS:如果业务场景需要,在外部控制表单的关闭时,只需要改变done functioncontext,也就是this指针指向<Form/>

总结

通过上述的transform函数,将原有的注入式组件转化为了命令式,简化了页面状态的维护,在通过mixins混入公有data以及method,简化了表单组件开发。上述方法也可用于开发toast、alert、confirm等组件,只需要将

Vue.prototype.method = transform(Toast-Component) 复制代码

原创声明: 该文章为原创文章,转载请注明出处。

你可能感兴趣的文章
SQL Server 临时表的删除
查看>>
程序8
查看>>
【原】WebRebuild深圳站的一点感悟
查看>>
QT Basic---Widgets<1>
查看>>
Android开发10.3:UI组件GridView网格视图
查看>>
Power BI的一些视频演示资源
查看>>
TBluetoothLEDevice.UpdateOnReconnect
查看>>
QtTableView 简介
查看>>
Linux系统上安装软件(ftp服务器)
查看>>
[iOS] App引导页的简单实现 (Swift 2)
查看>>
MHA 代码解析(online swtich+master is alive 模式)
查看>>
利用openssl进行RSA加密解密
查看>>
盒模型--边界
查看>>
14.使用通配符
查看>>
软件的模块化开发
查看>>
腾讯、百度、阿里面试经验—(3)阿里面经
查看>>
稍复杂的ionic例子:显示一个列表,并且允许点击进入列表项
查看>>
一些新的web性能优化技术
查看>>
Liferay 6开发学习(二十六):数据库连接相关问题
查看>>
【转】半路学编程,可以成为大牛吗?
查看>>