利用Vue構造器建立Form元件的通用解決方法
在前端平常的業務中,無論是官網、展示頁還是後臺運營系統都離不開表單,它承載了大部分的資料採集工作。所以如何更好地實現它,是平常工作中的一個重要問題。
在應用Vue框架去開發業務時,會將頁面上每個獨立的可視/可互動區域拆分為一個元件,再通過多個元件的自由組合來組成新的頁面。例如
...
...
當用戶的某個行為觸發表單時(例如註冊、建立內容等),期望在頁面中彈出一個From元件。通常的做法是在template中填入一個
元件的子類const _constructor = Vue.extend(component)
然後return function,它的功能是:
- 將元件轉化為method
- 在method呼叫時,將元件例項化並傳遞propsData
const {
propsData
} = options
let instance = new _constructor({
propsData
}).$mount(document.('div'))
為了能夠控制例項化後的元件,選擇instance返回。 當元件例項化時,它只是掛載到document.('div')上,但是並沒有掛載到頁面上,所以需要將其到頁面中。為了更好的語義化,選擇在元件的生命週期中完成它在頁面中的掛載。例項化時,會觸發元件mounted生命週期,所以當其觸發時可以掛載在document.body中,具體如下
mounted () {
document.body.(this.$el)
}
有了掛載,就必須要有登出。對應的生命週期應該是destroyed,所以
method: {
destroyElement () {
this.$destroy()
} //歡迎加入前端全棧開發交流圈一起學習交流:864305860
},
destroyed () {
this.$el.parentNode.removeChild(this.$el)
}
元件登出的時間與它在頁面中顯示息息相關,當
在頁面中不可見時候,需要登出它method: {
destroyElement () {
this.$destroy()
} //歡迎加入前端全棧開發交流圈一起學習交流:864305860
},
destroyed () {
this.$el.parentNode.removeChild(this.$el)
}
一般Form元件有兩個功能:
- done:代表使用者確認;
- cancel:代表使用者取消;
當done或cancel觸發時,APP元件內可能會有相應的變化,所以在元件例項化之後,利用$on去監聽對應的done事件以及cancel事件。
done && inlineListen({
method: 'done',
options,
instance
})//歡迎加入前端全棧開發交流圈一起吹水聊天學習交流:864305860
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.('div'))
instance.$on('done', data => resolve(data))
})//歡迎加入前端全棧開發交流圈一起學習交流:864305860
}
}//幫助突破技術瓶頸,提升思維能力
使用
可以將上述屬於
公有的data以及method獨立出來,再通過mixins引入到每個表單內,例如export default {
data() {
return {
visible: true
}
},
watch: {
visible(newValue) {
if (!newValue) {
this.destroyElement()
}
}
},
mounted() {
document.body.(this.$el)
},
destroyed() {
this.$el.parentNode.removeChild(this.$el)
},
methods: {
destroyElement() {
this.$destroy()
},
close() {
this.visible = false
}//歡迎加入前端全棧開發交流圈一起學習交流:864305860
}//面向1-3年前端人員
}//幫助突破技術瓶頸,提升思維能力
再通過mixins混入。
<>
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)
}//歡迎加入前端全棧開發交流圈一起學習交流:864305860
}
}//面向1-3年前端人員
}
}//幫助突破技術瓶頸,提升思維能力
>
呼叫時,只需
export default {
name: 'App',
methods: {
register: transform(register),
handleClick () {
this.register({
propsData: {
...
},
// done: data => function
done () {
// 外部關閉
this.close()
}//歡迎加入前端全棧開發交流圈一起學習交流:864305860
})
}//面向1-3年前端人員
}
}//幫助突破技術瓶頸,提升思維能力
PS:如果業務場景需要,在外部控制表單的關閉時,只需要改變done function的context,也就是this指標指向
。總結
通過上述的transform函式,將原有的注入式元件轉化為了命令式,簡化了頁面狀態的維護,在通過mixins混入公有data以及method,簡化了表單元件開發。上述方法也可用於開發toast、alert、confirm等元件,只需要將
Vue.prototype.method = transform(Toast-Component)
結語
感謝您的觀看,如有不足之處,歡迎批評指正。