Thinking系列,旨在利用10分钟的时间传达一种可落地的编程思想。
Normalize
标准化:Normalize
发组件过程中,为了提高组件的灵活性,我们通常需要支持多种传参格式,如何优雅的控制和组件内部解耦变得尤为重要!
示例: Vue的 clip-board 指令,支持两种传参方式。
- 如果是字符串,则为要拷贝的文本内容
- 如果是对象,对象中的text属性,为要拷贝的文本内容
<div v-clip-board="txt"></div>
<div v-clip-board="{text: 'txt', success, error}"></div>
传统写法
const _noop = function () { return {} }
const ClipBoard = require('clipboard')
export default {
name: 'clip-board',
hooks: {
bind: function (el, binding, vnode) {
const clipboard = new ClipBoard(el, {
action () { return binding.arg === 'cut' ? 'cut' : 'copy' }
})
// 判断是否为对象,并解构对象属性
if (typeof (binding.value) === 'object') {
let { success = _noop, error = _noop } = binding.value
clipboard.on('success', e => {
success()
})
clipboard.on('error', e => {
error()
})
}
el._clipboard = clipboard
},
update (el, binding) {
el._clipboard.text = function () {
// 判断是否为对象,处理相关值
return typeof (binding.value) === 'string' ? binding.value : binding.value.value
}
},
unbind (el, binding) {
el._clipboard.destroy()
delete el._clipboard
}
}
如果增加第三种参数支持,如数组格式,该如何处理?bind
和 update
方法中都需要增加判断分支。
Normalize后
const _noop = function () {}
// 集中化处理参数
const normalizeProps = function (param) {
let obj = {
text: '',
action: param.arg ? param.arg : 'copy',
success: _noop,
error: _noop
}
let type = Object.prototype.toString.call(param.value).match(/^\[object (.*)\]$/)[1].toLowerCase()
switch (type) {
case 'string':
obj.text = param.value
break
case 'object':
obj = Object.assign({}, obj, param.value)
break
default:
break
}
return obj
}
const ClipBoard = require('clipboard')
export default {
name: 'clip-board',
hooks: {
bind: function (el, binding, vnode) {
let { action, success, error } = normalizeProps(binding)
const clipboard = new ClipBoard(el, {
action () { return action }
})
clipboard.on('success', e => {
success()
})
clipboard.on('error', e => {
error()
})
el._clipboard = clipboard
},
update (el, binding) {
el._clipboard.text = function () {
return normalizeProps(binding)['text']
}
},
unbind (el, binding) {
el._clipboard.destroy()
delete el._clipboard
}
}
}
优势:
- 统一了判断入口,核心代码省掉了不必要的分支判断,简单明了;
- 后续需要增加其他格式属性时,核心代码无需修改,只需调整 normalize 函数。
哪里还有类似的场景出现?
以 Vue 中 Props 为例,进行说明
https://github.com/vuejs/vue/blob/dev/src/core/util/options.js#L298
props: ["propA"]
props: {
propB: Object,
propC: {
type: String
}
}
延伸
外观设计模式: