從一個 Confirm
組件開始,一步步寫一個可插拔式的組件。html
處理一個正常的支付流程(好比支付寶購買基金)前端
大約6個彈窗...vue
首先嚐試以一個日常的註冊組件實現git
Confirm
經過 v-model="isShow"
切換展現,經過 @onConfirm
和 onCancel
接收點擊事件。github
組件代碼ajax
<template>
<div v-if="value">
<slot></slot>
<div>
<div @click="cancelHandler">{{cancelTxt}}</div>
<div @click="confirmHandler">{{confirmTxt}}</div>
</div>
</div>
</template>
<script>
export default {
props: {
value: {
type: Boolean,
default: false,
}
},
data() {
return {
content: '',
confirmTxt: '',
cancelTxt: '',
}
},
methods: {
close() {
this.$emit('input');
},
cancelHandler() {
this.$emit('onCancel');
},
confirmHandler() {
this.$emit('onConfirm');
}
}
}
</script>
複製代碼
使用代碼bash
<confirm v-model="isConfirmShow" @onCancel="onCancel" @onConfirm="onConfirm" >內容部分</confirm>
複製代碼
那麼用它來完成上面的需求吧。app
openRiskConfirm() {
this.isRiskConfirmShow = true;
},
onRiskCancel() {
this.isRiskConfirmShow = false;
},
onRiskConfirm() {
// something
this.openPaymeList();
},
openPaymeList() {
this.isPaymentListShow = ture;
}
// ... 巴拉巴拉
// ... 大約須要 3*6 = 18 個方法才能完成需求(其餘請求類的還不算)
複製代碼
若是你能接受,可是:學習
那麼萬一監管放鬆了,不須要校驗風險了呢?或者一開始沒有校驗風險,監管忽然要校驗風險了呢?又或者不在 app
上使用,不用調用指紋呢?又或者要添加一個 人臉識別功能了呢?優化
代碼改起來會是一個災難,由於就算業務代碼是你寫的,你一段時間後也不必定能記得流程,並且,代碼看起來沒有任何的連續性,只能一個個方法看。
針對上面的業務流程,嘗試使用如今比較流行的的彈窗。
組件:更改接收方法位置,從 props
放到 $data
中
<template>
<div>
<div>{{content}}</div>
<div>
<div @click="cancelHandler">{{cancelTxt}}</div>
<div @click="confirmHandler">{{confirmTxt}}</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
content: '',
confirmTxt: '',
cancelTxt: '',
onConfirm: function() {},
onCancel: function() {},
}
},
methods: {
uninstall() {
this.$destroy(true);
this.$el.parentNode.removeChild(this.$el);
},
cancelHandler() {
(typeof this.onCancel === 'function') && this.onCancel()
this.uninstall();
},
confirmHandler() {
(typeof this.onConfirm === 'function') && this.onConfirm()
this.uninstall();
}
}
}
</script>
複製代碼
註冊到全局
import confirm from './confirm.vue'
export default {
install: function(Vue) {
const Profile = Vue.extend(confirm);
const PortfolioMsg = (options) => {
let $ele = document.createElement("div");
document.body.appendChild($ele);
new Profile({
data() {
return options;
}
}).$mount($ele);
};
Vue.prototype.$confirm = PortfolioMsg;
}
}
複製代碼
調用
this.$confirm({
content: '內容',
confirmTxt: '肯定',
cancelTxt: '取消',
onConfirm: () => {
console.log('肯定')
},
onCancel: () => {
console.log('取消')
}
})
複製代碼
哪啊麼用它完成上面的需求會如何?
this.$confirm({
content: '風險認證',
cancelTxt: '再看看',
confirmTxt: '贊成',
onConfirm: () => {
// something
this.$dialog({
content: '指紋認證',
slot: `<div>指紋認證</div>`,
onFinish: () => {
// 支付 成功? 失敗?
// something
},
onCancel: () => {
// something
this.$confirm({
content: '密碼認證',
cancelTxt: '取消',
confirmTxt: '肯定',
onConfirm: () => {
// something
this.$keyboard({
// 略
onFinish: (password) => {
// 密碼加密
// something
if (/* 密碼錯誤? */) {
// 重複了
// 這個代碼就能夠抽象成一個方法
this.$confirm({
content: '密碼認證',
cancelTxt: '取消',
confirmTxt: '肯定',
// 略
})
}
}
})
},
onCancel: () => {
// 取消
}
})
}
})
},
onCancel: () => {
// 取消
}
})
複製代碼
這樣看起來確實清晰了不少,代碼量也少了不少,不須要註冊全局的組件能夠經過在 methods
中封裝一個方法實現,維護起來也方便了不少。可是:回調地獄有木有?也只是稍微輕鬆一點,可不能夠再優化一下呢?
ajax 的回調地獄能夠經過 Promise
解決,那麼上面的組件回調地獄是否是也可使用 Promise
呢?
import confirm from './confirm.vue'
export default {
install: function(Vue) {
const Profile = Vue.extend(confirm);
const PortfolioMsg = (options) => {
let $ele = document.createElement("div");
document.body.appendChild($ele);
const profile = new Profile({
data() {
return options;
}
}).$mount($ele);
return new Promise((resolve, reject) => {
profile.$on('onConfirm', resolve)
profile.$on('onCancel', reject)
})
};
Vue.prototype.$confirm = PortfolioMsg;
}
}
複製代碼
使用一下
this.$confirm({
confirmTxt: '肯定'
}).then(res => {
console.log('點擊了肯定')
}).catch(res => {
console.log('點擊了取消')
})
複製代碼
那麼回調地獄的問題很輕鬆的就解決了,可讀性很高,中間添加刪除邏輯也變的特別方便,維護起來成本大大的下降了。具體代碼本身抽象一遍或許更好哦。
你們其餘的封裝方法嗎?請留言哈
譯者寫了一個 React + Hooks 的 UI 庫,方便你們學習和使用,
歡迎關注公衆號「前端進階課」認真學前端,一塊兒進階。