职责链的使用
职责链设计模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许将请求沿着处理者链传递,直到有一个处理者能够处理该请求为止。这种模式的核心思想是解耦请求的发送者和接收者,使得多个对象都有机会处理请求,而无需明确指定具体的处理者。
以下是js版本的封装
// 职责链模式安装 将其扩展到Function的原型链上,方便使用
export function dutyChainInstall() {
Function.prototype.dutyChain = function (fn) {
const self = this
return function (this: any, ...args) {
const ret = self.apply(this, args)
if (ret === 'nextSuccessor') {
return fn.apply(this, args)
}
return ret
}
}
}
// 如果使用了ts 要在全局d.ts中去扩展类型
declare interface Function {
dutyChain: (fn: any) => (...args: any) => any
}
根据对象的不同 需要不同的加工处理时,或者一个函数里 有很多if else的长链条时,可以使用职责链进行优化代码结构
使用示例
对于页面渲染要根据情况进行不同的处理时
职责链+自义定指令 让HTML部分以简单的方式去渲染,将不同情况的处理放在指令里。
import type { App } from 'vue'
// 联系方式隐藏指令
// 使用:
export function phoneHideInstall(app: App) {
// 判断是否登录
function isLogin(el: HTMLElement, arg: string, value: boolean) {
// 未登录则向下进行
if (!value) {
return 'nextSuccessor'
}
}
// 对联系人名字的处理
function nameHide(el: HTMLElement, arg: string) {
const text = el.innerText
if (arg === 'name' && !el.innerText.includes('*')) {
// 只保留第一个文字 其余部分文字变成*
if (!text) return
const num = text.length
el.innerText = text.slice(0, 1) + '*'.repeat(num - 1)
} else {
return 'nextSuccessor'
}
}
// 手机号处理
function mobileHide(el: HTMLElement, arg: string) {
const text = el.innerText
// 判断是正常手机号 且没有被处理过的情况进行处理
if (arg === 'phone' && !text.includes('-') && !text.includes('*')) {
const hideText = text.slice(3, 7)
el.innerHTML = text.replace(hideText, '****')
} else {
return 'nextSuccessor'
}
}
// 座机号处理
function landlineHide(el: HTMLElement, arg: string) {
const text = el.innerText
// 座机 以010-开头进行处理
if (arg === 'phone' && !text.includes('*')) {
const hideText = text.slice(5, 9)
el.innerHTML = text.replace(hideText, '****')
} else {
return 'nextSuccessor'
}
}
// 创造 隐藏手机号职责链
const phoneChain = isLogin.dutyChain(nameHide)
.dutyChain(mobileHide)
.dutyChain(landlineHide)
app.directive('phoneHide', (el, binding) => {
// 职责链去执行判断
phoneChain(el, binding.arg, binding.value)
})
}
<span v-phone-hide:name='true'>12345678910</span>
<span v-phone-hide:phone='true'>12345678910</span>
<span v-phone-hide:phone='false'>010-12345678</span>