前言
在前端平常的業務中,無論是官網、展示頁還是后臺運營系統都離不開表單,它承載了大部分的數據采集工作。所以如何更好地實現它,是平常工作中的一個重要問題。
在應用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>
新聞熱點
疑難解答
圖片精選