欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用Vue構(gòu)造器創(chuàng)建Form組件的通用解決方法

 更新時(shí)間:2018年12月03日 11:14:42   作者:FatGe  
這篇文章主要給大家介紹了關(guān)于利用Vue構(gòu)造器創(chuàng)建Form組件的通用解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

在前端平常的業(yè)務(wù)中,無(wú)論是官網(wǎng)、展示頁(yè)還是后臺(tái)運(yùn)營(yíng)系統(tǒng)都離不開(kāi)表單,它承載了大部分的數(shù)據(jù)采集工作。所以如何更好地實(shí)現(xiàn)它,是平常工作中的一個(gè)重要問(wèn)題。

在應(yīng)用Vue框架去開(kāi)發(fā)業(yè)務(wù)時(shí),會(huì)將頁(yè)面上每個(gè)獨(dú)立的可視/可交互區(qū)域拆分為一個(gè)組件,再通過(guò)多個(gè)組件的自由組合來(lái)組成新的頁(yè)面。例如

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

當(dāng)用戶的某個(gè)行為觸發(fā)表單時(shí)(例如注冊(cè)、建立內(nèi)容等),期望在頁(yè)面中彈出一個(gè)From組件。通常的做法是在template中填入一個(gè)<form>組件用于開(kāi)發(fā),并通過(guò)控制data中的UI.isOpen來(lái)對(duì)其display進(jìn)行控制,例如在當(dāng)前<template>組件內(nèi)開(kāi)發(fā)

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

這樣開(kāi)發(fā)有一點(diǎn)優(yōu)勢(shì),F(xiàn)orm組件與其父組件之間可以通過(guò)prop以及$emit方便通信。但是也會(huì)有以下幾個(gè)缺陷:

  • 當(dāng)前組件的data必須要有UI.isOpen來(lái)控制表單,如果存在多個(gè)表單時(shí),就會(huì)有大量的狀態(tài)來(lái)維護(hù)表單的開(kāi)關(guān);
  • 如果表單多次彈出時(shí),可能需要對(duì)表單的data進(jìn)行重置;
  • 與組件化思想相違背,表單不屬于當(dāng)前頁(yè)面,它只是由于用戶行為觸發(fā)的結(jié)果。

為了解決以上缺陷,并且還能具備方便通信的優(yōu)勢(shì),本文選擇用Vue.extend將原有<form>組件轉(zhuǎn)化為method function,并維護(hù)在當(dāng)前組件的method中,當(dāng)用戶觸發(fā)時(shí),在頁(yè)面中掛載,關(guān)閉時(shí)自動(dòng)注銷。

實(shí)例

演示地址:演示實(shí)例

代碼地址:FatGe github (本地下載)

APP組件

<template>
 <div id="app">
 <el-button 
  type="primary" icon="el-icon-edit-outline"
  @click="handleClick"
 >注冊(cè)</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>

當(dāng)<el-button>的點(diǎn)擊事件觸發(fā)時(shí),調(diào)用register方法,將表單組件掛載在頁(yè)面中。

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組件內(nèi)并未維護(hù)<form>組件的狀態(tài),其打開(kāi)或關(guān)閉只維護(hù)在自身的data中。

原理

上述代碼中,最為關(guān)鍵的一步就是transform函數(shù),它將原有的`從single-file components轉(zhuǎn)化為了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)創(chuàng)建一個(gè)<Form/>組件的子類

const _constructor = Vue.extend(component)

然后return function,它的功能是:

  • 將<form />組件轉(zhuǎn)化為method
  • 在method調(diào)用時(shí),將組件實(shí)例化并傳遞propsData
const {
 propsData
} = options
let instance = new _constructor({
 propsData
}).$mount(document.createElement('div'))

為了能夠控制實(shí)例化后的組件,選擇instance返回。

當(dāng)組件實(shí)例化時(shí),它只是掛載到document.createElement('div')上,但是并沒(méi)有掛載到頁(yè)面上,所以需要將其appendChild到頁(yè)面中。為了更好的語(yǔ)義化,選擇在組件的生命周期中完成它在頁(yè)面中的掛載。實(shí)例化時(shí),會(huì)觸發(fā)組件mounted生命周期,所以當(dāng)其觸發(fā)時(shí)可以掛載在document.body中,具體如下

mounted () {
 document.body.appendChild(this.$el)
}

有了掛載,就必須要有注銷。對(duì)應(yīng)的生命周期應(yīng)該是destroyed,所以

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

組件注銷的時(shí)間與它在頁(yè)面中顯示息息相關(guān),當(dāng)<form />在頁(yè)面中不可見(jiàn)時(shí)候,需要注銷它

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

一般Form組件有兩個(gè)功能:

  • done:代表用戶確認(rèn);
  • cancel:代表用戶取消;

當(dāng)done或cancel觸發(fā)時(shí),APP組件內(nèi)可能會(huì)有相應(yīng)的變化,所以在組件實(shí)例化之后,利用$on去監(jiān)聽(tīng)對(duì)應(yīng)的done事件以及cancel事件。

done && inlineListen({
 method: 'done',
 options,
 instance
})
cancel && inlineListen({
 method: 'cancel',
 options,
 instance
})

其中inlineListen函數(shù)可以方便后續(xù)添加其他的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獨(dú)立出來(lái),再通過(guò)mixins引入到每個(gè)表單內(nèi),例如

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

再通過(guò)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>

調(diào)用時(shí),只需

export default {
 name: 'App',
 methods: {
 register: transform(register),

 handleClick () {
  this.register({
  propsData: {
   ...
  },
  // done: data => function
  done () {
   // 外部關(guān)閉
   this.close()
  }
  })
 }
 }
}

PS:如果業(yè)務(wù)場(chǎng)景需要,在外部控制表單的關(guān)閉時(shí),只需要改變done function的context,也就是this指針指向<Form/>。

總結(jié)

通過(guò)上述的transform函數(shù),將原有的注入式組件轉(zhuǎn)化為了命令式,簡(jiǎn)化了頁(yè)面狀態(tài)的維護(hù),在通過(guò)mixins混入公有data以及method,簡(jiǎn)化了表單組件開(kāi)發(fā)。上述方法也可用于開(kāi)發(fā)toast、alert、confirm等組件,只需要將
Vue.prototype.method = transform(Toast-Component)

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • vue2組件進(jìn)階與插槽詳解(推薦!)

    vue2組件進(jìn)階與插槽詳解(推薦!)

    插槽(slot)作用是讓父組件可以往子組件指定位置插入?html?結(jié)構(gòu),也是組件的一種通信方式,下面這篇文章主要給大家介紹了關(guān)于vue2組件進(jìn)階與插槽的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • vue仿element實(shí)現(xiàn)分頁(yè)器效果

    vue仿element實(shí)現(xiàn)分頁(yè)器效果

    這篇文章主要介紹了vue仿element實(shí)現(xiàn)分頁(yè)器效果,實(shí)現(xiàn)思路是定一個(gè)值foldPage, 意為當(dāng)前最多顯示的標(biāo)簽數(shù),當(dāng)總頁(yè)數(shù)超過(guò)即顯示省略.省略分為左邊省略(folder1)和右邊省略(folder2),具體實(shí)例代碼大家參考下本文
    2018-09-09
  • vue實(shí)例中data使用return包裹的方法

    vue實(shí)例中data使用return包裹的方法

    今天小編就為大家分享一篇vue實(shí)例中data使用return包裹的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • Vue路由切換頁(yè)面不更新問(wèn)題解決方案

    Vue路由切換頁(yè)面不更新問(wèn)題解決方案

    這篇文章主要介紹了Vue路由切換頁(yè)面不更新問(wèn)題解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 詳解Vue的computed(計(jì)算屬性)使用實(shí)例之TodoList

    詳解Vue的computed(計(jì)算屬性)使用實(shí)例之TodoList

    本篇文章主要介紹了詳解Vue的computed(計(jì)算屬性)使用實(shí)例之TodoList,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-08-08
  • Vue 2閱讀理解之initRender與callHook組件詳解

    Vue 2閱讀理解之initRender與callHook組件詳解

    這篇文章主要為大家介紹了Vue 2閱讀理解之initRender與callHook組件詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • axios封裝,使用攔截器統(tǒng)一處理接口,超詳細(xì)的教程(推薦)

    axios封裝,使用攔截器統(tǒng)一處理接口,超詳細(xì)的教程(推薦)

    這篇文章主要介紹了axios封裝使用攔截器處理接口,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • 解決Echarts 顯示隱藏后寬度高度變小的問(wèn)題

    解決Echarts 顯示隱藏后寬度高度變小的問(wèn)題

    這篇文章主要介紹了解決Echarts 顯示隱藏后寬度高度變小的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-07-07
  • Vue 設(shè)置axios請(qǐng)求格式為form-data的操作步驟

    Vue 設(shè)置axios請(qǐng)求格式為form-data的操作步驟

    今天小編就為大家分享一篇Vue 設(shè)置axios請(qǐng)求格式為form-data的操作步驟,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-10-10
  • Vue不能watch數(shù)組和對(duì)象變化解決方案

    Vue不能watch數(shù)組和對(duì)象變化解決方案

    這篇文章主要為大家介紹了Vue不能watch數(shù)組和對(duì)象變化解決方案示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11

最新評(píng)論