国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > JS > 正文

利用Vue構造器創建Form組件的通用解決方法

2024-05-06 16:47:22
字體:
來源:轉載
供稿:網友

前言

在前端平常的業務中,無論是官網、展示頁還是后臺運營系統都離不開表單,它承載了大部分的數據采集工作。所以如何更好地實現它,是平常工作中的一個重要問題。

在應用Vue框架去開發業務時,會將頁面上每個獨立的可視/可交互區域拆分為一個組件,再通過多個組件的自由組合來組成新的頁面。例如

<template> <header></header> ... <content></content> ... <footer></footer></template>

當用戶的某個行為觸發表單時(例如注冊、建立內容等),期望在頁面中彈出一個From組件。通常的做法是在template中填入一個<form>組件用于開發,并通過控制data中的UI.isOpen來對其display進行控制,例如在當前<template>組件內開發

<template> <header></header> ... <content></content> ... <footer></footer> ... <register-form v-if="UI.isOpen"> <form-item></form-item> ... <submit-button></submit-button> </register-form></template>

這樣開發有一點優勢,Form組件與其父組件之間可以通過prop以及$emit方便通信。但是也會有以下幾個缺陷:

  • 當前組件的data必須要有UI.isOpen來控制表單,如果存在多個表單時,就會有大量的狀態來維護表單的開關;
  • 如果表單多次彈出時,可能需要對表單的data進行重置;
  • 與組件化思想相違背,表單不屬于當前頁面,它只是由于用戶行為觸發的結果。

為了解決以上缺陷,并且還能具備方便通信的優勢,本文選擇用Vue.extend將原有<form>組件轉化為method function,并維護在當前組件的method中,當用戶觸發時,在頁面中掛載,關閉時自動注銷。

實例

演示地址:演示實例

代碼地址:FatGe github

APP組件

<template> <div id="app"> <el-button   type="primary" icon="el-icon-edit-outline"  @click="handleClick" >注冊</el-button> </div></template><script>import register from './components/register'import { transform } from './transform'export default { name: 'App', methods: { register: transform(register), handleClick () {  this.register({  propsData: { name: '皮鞋' },  done: name => alert(`${name}牛B`)  }) } }}</script>

當<el-button>的點擊事件觸發時,調用register方法,將表單組件掛載在頁面中。

Form組件

<template> <div class="mock" v-if="isVisible"> <div class="form-wrapper">  <i class="el-icon-close close-btn" @click.stop="close"></i>  ...<header />  ...<content />  <div class="footer">   <el-button     type="primary"    @click="handleClick"   >確定</el-button>   <el-button     type="primary"    @click="handleClick"   >取消</el-button>  </div> </div> </div></template><script>export default { porps: { ... }, data () { return {  isVisible: true } },  watch: { isVisible (newValue) {  if (!newValue) {  this.destroyElement()  } } },  methods: { handleClick ({ type }) {  const handler = {  close: () => this.close()  } }, destroyElement () {  this.$destroy() }, close () {  this.isVisible = false } },  mounted () { document.body.appendChild(this.$el) },  destroyed () { this.$el.parentNode.removeChild(this.$el) }}</script>

在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 }}

首先利用Vue.extend(options)創建一個<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 />在頁面中不可見時候,需要注銷它

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

一般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混入。

<script>import popupWin from '../mixins/popup-win'export default { mixins: [popupWin], data () { return {  input: '',  gender: 1 } }, methods: { handleClick ({ type }) {  const handler = {  close: () => this.close(),  confirm: () => {   const { input } = this   this.$emit('done', input)  }  } } }}</script>

調用時,只需

export default { name: 'App', methods: { register: transform(register), handleClick () {  this.register({  propsData: {   ...  },  // done: data => function  done () {   // 外部關閉   this.close()  }  }) } }}

PS:如果業務場景需要,在外部控制表單的關閉時,只需要改變done function的context,也就是this指針指向<Form/>。

總結

通過上述的transform函數,將原有的注入式組件轉化為了命令式,簡化了頁面狀態的維護,在通過mixins混入公有data以及method,簡化了表單組件開發。上述方法也可用于開發toast、alert、confirm等組件,只需要將
Vue.prototype.method = transform(Toast-Component)

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 沁源县| 东乡| 绍兴县| 庄浪县| 陆河县| 正宁县| 广元市| 海安县| 海原县| 长岭县| 当雄县| 凉城县| 镶黄旗| 石城县| 噶尔县| 寻甸| 玉山县| 河南省| 绿春县| 沂南县| 赤水市| 册亨县| 吴江市| 临汾市| 平顺县| 岳阳县| 河北省| 稷山县| 垫江县| 邯郸县| 麻江县| 西安市| 涞源县| 万安县| 叙永县| 潢川县| 太康县| 叶城县| 磐石市| 青海省| 盐城市|