亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 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教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
2019中文字幕全在线观看| 欧美日韩中文字幕日韩欧美| 欧美精品电影在线| 8050国产精品久久久久久| 国产日韩精品在线观看| 国产精品久久久久久影视| 国产在线高清精品| 久久精品国产99国产精品澳门| 亚洲影院高清在线| 91深夜福利视频| 国产精品视频一区二区三区四| 久久亚洲国产精品成人av秋霞| 色悠悠国产精品| 91在线观看免费观看| 成人激情视频免费在线| 日韩电影在线观看中文字幕| 91久久综合亚洲鲁鲁五月天| 热re99久久精品国产66热| 免费av一区二区| 91高清视频在线免费观看| 欧美一二三视频| 国产精品免费视频xxxx| 国产欧美一区二区三区四区| 精品亚洲国产成av人片传媒| 亚洲欧洲日产国产网站| 九九九热精品免费视频观看网站| 国产精品网红福利| 亚洲中国色老太| 亚洲区中文字幕| 亚洲最大福利视频网站| 伊人伊成久久人综合网小说| 17婷婷久久www| 国产成人精品久久久| 国产精品激情av在线播放| 久久天天躁狠狠躁夜夜av| 91欧美激情另类亚洲| 国产午夜一区二区| 亚洲自拍偷拍网址| 亚洲性无码av在线| 精品一区二区亚洲| 91精品国产综合久久香蕉的用户体验| 欧洲亚洲女同hd| 蜜臀久久99精品久久久久久宅男| 午夜精品久久久99热福利| 久久久av免费| 中国人与牲禽动交精品| 国产视频在线观看一区二区| 日韩av免费看| 国产精品国产三级国产aⅴ浪潮| 精品人伦一区二区三区蜜桃免费| 91禁外国网站| 国产精品欧美日韩| 欧美黑人狂野猛交老妇| 日韩精品在线观看一区| 国产欧美在线播放| 精品香蕉一区二区三区| 精品视频在线观看日韩| 亚洲激情小视频| 国产91在线播放精品91| 成人久久久久爱| 国产成人a亚洲精品| 国产视频精品免费播放| 自拍偷拍免费精品| 不卡伊人av在线播放| 日韩成人激情视频| 亚洲国产中文字幕在线观看| 久热精品在线视频| 久久久亚洲福利精品午夜| 97在线免费观看视频| 亚洲第一区第二区| 久青草国产97香蕉在线视频| 在线精品国产成人综合| 97视频在线观看成人| 国产精品电影网| 国产午夜精品全部视频在线播放| 国产婷婷色综合av蜜臀av| 久久青草福利网站| 精品国产成人av| 国产精品91免费在线| 国产精品日韩久久久久| 亚洲欧美成人在线| 欧美性猛交xxxx黑人猛交| 国产精选久久久久久| 欧美自拍视频在线观看| 国产美女扒开尿口久久久| 亚洲成人av在线播放| 日韩激情第一页| 亚洲精品98久久久久久中文字幕| 成人黄色午夜影院| 一夜七次郎国产精品亚洲| 一区二区成人av| 日韩欧美中文第一页| 久久香蕉频线观| 国产精品久在线观看| 久久久国产精品x99av| 精品国产乱码久久久久久婷婷| 欧美激情免费在线| 亚洲自拍高清视频网站| 国产成人精品久久二区二区| 国产欧亚日韩视频| 91wwwcom在线观看| 日韩av综合网| 精品久久在线播放| 日韩美女视频在线观看| 国产欧美va欧美va香蕉在| 欧美黑人巨大精品一区二区| 国产欧美精品一区二区三区介绍| 91av视频在线免费观看| 亚洲一区二区福利| 国产精自产拍久久久久久蜜| 亚洲国模精品一区| 国产精品自拍偷拍| 中文字幕欧美亚洲| 色悠悠久久88| 亚洲国产精品人人爽夜夜爽| 国产精品一区二区久久久久| 亚洲全黄一级网站| 亚洲欧美福利视频| 国产精品美女主播在线观看纯欲| 97在线免费视频| 国产精品电影网| 欧美激情精品久久久久久免费印度| 夜夜嗨av色一区二区不卡| 九九久久综合网站| 精品视频9999| 日本久久精品视频| 亚洲黄色av网站| 国产精品美女免费视频| 久久精品小视频| 欧美影院成年免费版| 久久精品国产成人精品| 不卡毛片在线看| 欧美性猛交xxxx乱大交极品| www国产精品com| 91精品视频在线看| 国产精品亚洲精品| 欧美成人免费观看| 国产精品v片在线观看不卡| 国产精品久久久久久久久久小说| 亚洲影院高清在线| 欧美激情欧美激情| 欧美黄色片免费观看| 亚洲女成人图区| 91在线高清视频| 国产综合色香蕉精品| 欧美精品在线观看91| 国产一区在线播放| 国产精品欧美日韩一区二区| 色99之美女主播在线视频| 色狠狠久久aa北条麻妃| 欧美又大又粗又长| 午夜精品一区二区三区在线| 欧美亚洲第一页| 久久久久久久电影一区| 亚洲精品视频二区| 日韩欧美精品在线观看| 国产综合在线观看视频| 亚洲欧美日韩一区二区三区在线| 97视频com| 午夜精品99久久免费| 一本一本久久a久久精品牛牛影视| 亚洲电影在线观看| www.日本久久久久com.| 色噜噜狠狠狠综合曰曰曰|