写这篇文章的想法,其实来自于本身的一次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 + ', 不要紧!')
})
}
复制代码