寫這篇文章的想法,其實來自於本身的一次React組件開發實踐(傳送門)。當時是作一個markdown編輯器,原理是用戶編輯事後的string,通過其餘開源的markdown語法解析器解析後輸出html格式的文檔,這樣就能夠實時預覽markdown了。開發初版時,我將解析器markdown-it內置在組件裏,雖然可以知足了需求,可是也帶來了一些問題:解析器會打包到本身的組件裏致使代碼體積增大,用戶不能自定義解析器(ps:就想用那誰誰家的,咋地)。後來在項目貢獻者sylingd的改造下,將組件的renderHtml接口改形成了一個高階函數,完美的解決了這個問題(在此表示衷心的感謝!)html
<div id="app" class='container'>
<div style='margin: 50px'>{{title}}</div>
<div style='margin: 20px; font-size: 16px'>{{message}}</div>
<my-button :tap='tapString' type='我是字符串'></my-button>
<my-button :tap='tapFunction' type='我是函數'></my-button>
<my-button :tap='tapPromise' type='我是promise'></my-button>
</div>
複製代碼
<script>
// 子組件
Vue.component('my-button', {
props: ['type'],
methods: {
handleClickMe: function () {
// 普通返回
var value = '我是一個普通數據類型,好比字符串,數字'
var middleware = this.$attrs.tap(value)
if (!middleware) {
console.log('返回undefined,直接終止')
return
}
if (typeof middleware === 'function') {
middleware('我是一個函數')
} else if (typeof middleware === 'object' && typeof middleware.then === 'function') {
middleware.then(({ payload, callback }) => {
typeof callback === 'function' && callback(payload + ', world!')
}).catch(({ payload, callback }) => {
typeof callback === 'function' && callback(payload + ', 不要緊!')
})
}
// ...其餘類型
}
},
template: '<button v-on:click="handleClickMe">點我, {{type}} </button>'
})
// 父組件
var app = new Vue({
el: '#app',
data: {
title: '父組件',
message: ''
},
methods: {
tapString: function (res) {
this.message = res
// alert(res)
},
tapFunction: function (res) {
var _this = this
return function (data) {
_this.message = data
// alert(data)
}
},
tapPromise: function (res) {
var _this = this
return new Promise((resolve, reject) => {
_this.message = ''
var number = Math.random()
setTimeout(() => {
if (number > 0.5) {
resolve({
payload: 'hello',
callback: function (res) {
_this.message = res
// alert(res)
}
})
} else {
reject({
payload: '發生錯誤了',
callback: function (res) {
_this.message = res
// alert(res)
}
})
}
}, 1000)
})
}
}
})
</script>
複製代碼
var middleware = this.$attrs.tap(value)
,而後經過判斷這個結果的類型,若是是函數或者是promise,再進行相應的處理便可。if (!middleware) {
return
}
if (typeof middleware === 'function') {
middleware('我是一個函數')
} else if (typeof middleware === 'object' && typeof middleware.then === 'function') {
middleware.then(({ payload, callback }) => {
typeof callback === 'function' && callback(payload + ', world!')
}).catch(({ payload, callback }) => {
typeof callback === 'function' && callback(payload + ', 不要緊!')
})
}
複製代碼