总结一下,前一段时间内写的一个需求的注意点。虽然仅仅是对一个封装好的sdk的调用,但是细挖的话,里面也有很多值得关注的点。写下来总结一下,不断进步!!!
首先来大概介绍一下需求,就是引入一个,已经封装好的客服sdk,功能就是可以实现,自动回复,以及转接人工这些。因为没有npm版本需要手动以script标签的形式。大概就是这样,下面分析我考虑不周的地方,以及遇到的问题。
first
首先呢,就是何时去初始化sdk.
这个sdk,在加载完毕之后会在window对象下面挂载一个函数(为了方便,这里我命名为fn),fn接收一个url 作为地址(url是iframe的url),fn接受一些钩子函数作为回调函数,在特定时机触发,返回一个promise,成功时resolve该sdk的实例,失败时reject sdk的错误信息。
他内部的ui以iframe形式展示,需要挂在到,dom实例上。
//初始化方法
window.fn({
//
target: document.getElementById('linkchatWrap'),
//
url: data,
//下面是一些勾子函数
showCallback: () => {
},
//展示时触发
hideCallback: () => {
},
//隐藏时触发
iframeOnloadCallback: () => {}
});
我们需要在组件渲染之前,引入sdk,
const handleLoadScript = () => {
const myScript = document.createElement('script');
myScript.src =
'sdk的url';
myScript.async = true;
myScript.onload = handleLoad;
document.body.appendChild(myScript);
};
当然我们又不能影响html 的加载,这里必须采用async的形式。那么问题就来了,根据async的机制,对应资源加载好之后立即执行,此时html不一定渲染好。引用一下如下的图
我们需要保证在执行初始化时 script 一定加载完成了,那怎么去保证呢。利用script 标签上面的onload就可以保证。ok,我们只需要在一个useEffect里面去调用 handleLoadScript即可。 然后在 handleLoad事件中去执行初始化。
const handleLoad = async () => {
try {
const data = await getUrl({ channel_id: 0 });
const linkInstance = await handleInitialize(data);
//初始化函数,调用初始化方法
} catch (e: any) {
//一些错误上报方式
}
};
const handleInitialize = (data: string) => {
return window.fn({
target: document.getElementById('linkchatWrap'),
url: data,
//下面是一些勾子函数
showCallback: () => {
},
//展示时触发
hideCallback: () => {
},
//隐藏时触发
iframeOnloadCallback: () => {}
});
};
如上所示,采用同步调用方式,需要先获取url ,再去调用,这个是必须要确保的。
到了这里,我们明确了script 加载的机制。以及何时去初始化。
second
那么接下来的问题,初始化完成后怎么去展示呢? 这个需求是,点击一个按钮去展示出来,并且可以拖拽移动位置。 好家伙,不就是一个modal组件吗。安排!拖拽就安利一个 react-draggable 库,挺好用的。利用fix 定位,使其对整个屏幕局中对齐。首先菜单栏里面有个在线客服,点击时候去展示sdk.
听起来很简单呀?并没有什么大问题。那么再仔细想想,仅仅就是去展示吗? 我们以一定是需要考虑一些错误情况。假如初始化没用成功怎么办?加入sdk引入失败怎么办?所以这个点击事件不仅要去展示,更要先去判断,是否可以展示。
const handleClick = async () => {
if (window.fn === undefined) {
handleLoadScript();‘
//没有引入成功就继续引入。
} else {
if (linkchat === undefined) {
//没初始化,就先初始化。
try {
const data = await getUrl({ channel_id: 0 });
const linkInstance = await handleInitialize(data);
setlinkchat(linkInstance);
linkInstance.show();
} catch (e) {
//省略错误处理
}
} else {
fn.show();
//正常就,调用展示。
}
}
};
以上两点,是值得关注的点,当然还有一些注意点,对一些复用逻辑进行封装。比如初始化,比如引入sdk这些。
值得强调的还是一定要在开发过程中注意细节,优化逻辑,避免冗杂代码,考虑错误边界。先构思之后再动手,还有就是养成复盘习惯哦