需求背景
对项目中引入的第三包的发送按钮进行动态配置,控制发送按钮的展示与隐藏。
已知:
- 发送按钮默认展示
- 能获取发送按钮的 class 类名(方便说明,假设该类名为
.chat-design-input-operation)。
思考过程
方案一
- 获取该元素
- 给该元素添加或删除样式
function handleSendBtn (btnShow: boolean) {
const btn = document.querySelector('.chat-design-input-operation')
if (btnShow) {
btn.classList.remove('.chat-design-input-operation-hiddern')
} else {
btn.classList.add('.chat-design-input-operation-hiddern')
}
}
缺点:只适用第三方包元素常驻情况,若该元素需要特定条件才渲染,且我们无法获取第三包特定渲染条件,该方法不适用
方案二
- 按需载入css文件
function handleSendBtn (btnShow: boolean) {
if (btnShow) {
// do-nothing
} else {
import('./hidden.css')
}
}
.chat-design-input-operation {
display: none
}
缺点:css文件一旦引入,无法移除,不能实现切换按钮的展示与隐藏。只适用于元素样式改变一次的情况。
方案三(最终方案)
虽然方案二最终未使用,但给了我思考问题的方向。动态导入 css 文件,其实就是在页面中插入了 style 标签,那我何尝不自己特定的 style 片段进行样式的控制呢,说干就干:
- 新建一个 style 标签,设置唯一标识(方便后面移除)
- style 标签设置按钮隐藏样式
- 根据条件插入/移除 style 标签
function handleSendBtn (btnShow: boolean) {
const styleId = 'IM-sendBtn-config';
if (btnShow) {
const styleElement = document.querySelector(`[data-style-id="${styleId}"]`)
styleElement && document.head.removeChild(styleElement)
} else if (sendType === 'button') {
const styleElement = document.createElement('style')
styleElement.setAttribute('data-style-id', styleId)
styleElement.innerHTML = `
.chat-design-input-operation {
display: none;
}
`
document.head.appendChild(styleElement)
}
}
最终效果
发送按钮展示
发送按钮隐藏
思考
本需求虽然在实现方案上比较简单,但一不小心很容易掉坑里,比如使用 MutationObserver 监听 DOM 变化继续沿用方案一,但使用 MutationObserver 监听 DOM 这一方式并不准确,不一定能获取到你想要的目标元素。所以,做需求很重要的一点就是:发现思路不对,及时掉头,避免自己踩坑,给别人挖坑。