tauri学习(2)-a链接伪类visited失效问题
接上节继续,在前端开发中,a链接常用a:visited伪类,用于区分链接点击过后的呈现效果。
在tauri项目模板中,把App组件中添加3个链接:
然后在App.css中添加几个样式:
程序跑起来后,却意外发现:其它几个伪类都起作用,唯独:visited这个伪类,在tairu桌面应用中一点反应都没有,参见下面,上面为tauri桌面应用,下面为浏览器窗口。
从动图效果看出,在浏览器中:visited是能正常生效的,点击后的链接显示为orange橙色,但是在上面的tauri应用中却没反应。其实不光是tauri有这个问题,electron同样也有类似问题。
StackOverFlow上有外国网友给出了解决思路:将访问过的链接,写入localStorage中,然后在组件生命周期的DidUnmount中,给这些链接,强行附加一个额外样式。
先定义2个常量,分别用于localStorage存放访问过的a链接记录,另1个则是强行附加的样式类名
const LOCAL_STORAGE_HISTORY_KEY = "visitedHistory"; const VISITED_CLASS_NAME = "visited";
核心代码1:setVisited
从localStorage中取出点击过的a链接记录(先不管如何存入localStorage的,后面会讲到,假如已经有了),然后判断记录是否过期,如果过期了则删除(重要!否则一直不停点,一直不停向localStorage中存,列表越来越大,早晚崩溃),然后将每个a链接的href跟访问记录匹配,对上了,则追加1个visited的样式(当然:这个样式要额外写)
/** * 根据localStorage里的历史记录,将a附加上visited样式 * by 菩提树下的杨过http://yjmyzz.cnblogs.com/ */ function setVisited() { let localstorageSimuHistory = localStorage.getItem(LOCAL_STORAGE_HISTORY_KEY); let simuHistory = localstorageSimuHistory ? JSON.parse(localstorageSimuHistory) : []; //过期访问记录清理 const now = new Date(); let hasExpired = false; for (let i = simuHistory.length - 1; i >= 0; i--) { let item = simuHistory[i]; //过期的访问记录删除 if (now.getTime() > item.expire) { simuHistory.splice(i, 1) hasExpired = true } } if (hasExpired) { if (simuHistory.length <= 0) { localStorage.removeItem(LOCAL_STORAGE_HISTORY_KEY); } else { localStorage.setItem(LOCAL_STORAGE_HISTORY_KEY, JSON.stringify(simuHistory)); } } //遍历所有a,访问过的,则强制附加visited样式 let elements = document.getElementsByTagName('a'); for (let i = 0; i < elements.length; i++) { for (let h = 0; h < simuHistory.length; h++) { if (elements[i].href === simuHistory[h].url && elements[i].className.indexOf(VISITED_CLASS_NAME) === -1) { elements[i].className += ` ${VISITED_CLASS_NAME}`; } } } }
localStorage中的数据,大致长这样:
核心代码2:addHref
每个链接点击后,将自身的href存入localStorage
/** * a链接点击后将url加入localStorage * @param url */ function addHref(url: String) { let localstorageSimuHistory = localStorage.getItem(LOCAL_STORAGE_HISTORY_KEY); let simuHistory = localstorageSimuHistory ? JSON.parse(localstorageSimuHistory) : []; let found = false; const now = new Date(); //访问记录过期时间设置(此处仅为示例:30秒) const ttl: number = 1000 * 30; for (let i = simuHistory.length - 1; i >= 0; i--) { let item = simuHistory[i]; if (item.url === url) { found = true; //过期时间续租 simuHistory[i] = { "url": url, "expire": new Date().getTime() + ttl }; break; } } //如果本链接不在访问列表里,则添加 if (!found) { simuHistory[simuHistory.length] = { "url": url, "expire": new Date().getTime() + ttl }; localStorage.setItem(LOCAL_STORAGE_HISTORY_KEY, JSON.stringify(simuHistory)); } //此处只是为了方便,把所有点过的a全刷了一把,还可以再优化下(略) setVisited(); }
核心代码3:bindAddHref
给每个a链接的click绑定事件
function bindAddHref() { let elements = document.getElementsByTagName('a'); for (let i = 0; i < elements.length; i++) { elements[i].onclick = () => { addHref(elements[i].href); } } setVisited(); }
有了上面3个核心方法,就可以在App的生命周期"DidMount"挂载阶段,调用bindAddHref,为每个a链接自动绑定click事件
当然App.css里得手动添加.visited样式
.visited { color: orange !important }
最后运行的效果如下:
从运行效果上看,"大致"跟浏览器上的表现相同,但值得说明的是,这毕竟只是一种变相的解决方法,二者还是有差别的,如果用开发者工具,把localStorage清了,而浏览器并不清除缓存(反过来也一样),二者的表现还是有差异,不过大多数情况下,上述解决方案,应该能满足业务要求了。
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。