离站链接风险提示页的简单实现
轻模式-监听事件拦截
通过以下几个步骤,可实现对全局a标签的跳转监听、阻止效果。提取到跳转参数后,可以统一跳转到指定路径去进行二次确认跳转及跳转路径安全的验证。
- 监听页面中所有点击,提取点击的链接,并阻止a标签的原生跳转
- 根据提取到的连接,进行自定义从新跳转,比如本域直接跳转,外链先跳转风险提示页
示例代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<a href="/about" target="_blank">站内链接</a>
<a href="https://www.baidu.com/" target="_blank">baidu</a>
<script>
document.body.addEventListener("click", function (event) {
var target = event.target || event.srcElement; // 兼容处理
if (target.nodeName.toLocaleLowerCase() === "a") { // 判断是否匹配目标元素
if (event.preventDefault) { // 对捕获到的 a 标签进行处理
event.preventDefault();
} else {
window.event.returnValue = true;
}
choosePush(target); // 处理完 a 标签的内容,重新触发跳转,根据原来 a 标签页 target 来判断是否需要新窗口打开
}
}.bind(this));
function choosePush(el) {
const target = el.getAttribute("target");
const href = el.getAttribute("href");
var domain = window.location.host.toLowerCase();
if (href.indexOf(window.location.host) >= 0) {
window.location.href = href;
}
else {
window.open('/link?target=' + encodeURIComponent(href));
}
}
</script>
</body>
</html>
js监听浏览器离开页面操作
unload onbeforeunload 事件处理
//body
{/* <body onbeforeunload="goodbye()"> */}
//window
window.onunload=function(e){
var e = window.event||e;
}
//window
window.onbeforeunload=function(e){
var e = window.event||e;
e.returnValue=("确定离开当前页面吗?");
}
window.onunload = window.onbeforeunload = (function(){
var didMyThingYet=false;
return function(){
if (didMyThingYet) return;
didMyThingYet=true;
// do your thing here...
}
}());
// Or attachEvent:
(function(){
var didMyThingYet=false;
function listener (){
if (didMyThingYet) return;
didMyThingYet=true;
// do your thing here...
}
window.attachEvent("onbeforeunload", listener);
window.attachEvent("onunload", listener);
}());
重模式-替换所有连接
前端链接处理
正则表达式替换所有链接
// utils/index.js
/**
* 替换富文本中的链接
* 将富文本中的不是本站的链接前追加 "https://link.juejin.cn/?target="
* @param html 传入富文本
* @returns html 处理后的富文本
*/
export const replaceHTMLHref = (html) => {
const juejinReg = /https:\/\/juejin.cn/g; // 匹配"https://juejin.cn"
const juejinSignReg = /JUEJIN_URL/g; // 匹配"JUEJIN_URL"
const urlReg =
/((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*(?!juejin.cn)[\w\-\@?^=%&/~\+#])?)/g; // 匹配所有网址
/**
* 匹配替换三次
* 第一次将所有"https://juejin.cn"替换为"JUEJIN_URL"
* 第二次将所有网址增加前缀"https://link.juejin.cn/?target="
* 第三次将所有"JUEJIN_URL"替换为"https://juejin.cn"
*/
const result = html
.replace(juejinReg, "JUEJIN_URL")
.replace(urlReg, "https://link.juejin.cn/?target=$1")
.replace(juejinSignReg, "https://juejin.cn");
return result;
};
一段测试代码
// 省略其他非关键代码
import { replaceHTMLHref } from "@/utils";
const str = '一个外部网址:\nhttps://cn.bing.com/\n又一个外部网址:\nhttps://www.baidu.com/\n掘金:\nhttps://juejin.cn/';
console.log(replaceHTMLHref(str));
附 风险提示页vue实现
// 风险提示页
<template>
<div class="box">
<div class="tip-box">
<img
class="logo"
src="https://lf-cdn-tos.bytescm.com/obj/static/link_juejin_cn/assets/logo_new.0ec938fb.svg"
/>
<div class="content">
<div class="title">
即将离开稀土掘金,请注意账号财产安全
</div>
<div class="link">{{ target }}</div>
<button class="btn" @click="navigateToTarget">继续访问</button>
</div>
</div>
</div>
</template>
<script>
export default {
name: "RiskTip",
data() {
return { target: "" };
},
methods: {
// 获取 url
getTargetURL() {
const query = window.location.href.split("?")[1] || "";
const target = query.split("target=")[1] || "";
this.target = window.decodeURIComponent(target);
},
// 跳转页面
navigateToTarget() {
if (!this.target) {
return;
}
window.location.href = this.target;
},
},
mounted() {
this.getTargetURL(); // 获取 url
},
};
</script>
<style scoped>
.box {
height: 100vh;
background-color: #f4f5f5;
}
.box .tip-box {
position: absolute;
left: 50%;
top: 30%;
max-width: 624px;
width: 86%;
background-color: #fff;
transform: translateX(-50%);
padding: 30px 40px 0;
box-sizing: border-box;
border: 1px solid #e5e6eb;
border-radius: 2px;
}
.box .tip-box .logo {
display: block;
width: 116px;
height: 24px;
position: absolute;
top: -40px;
left: 0;
}
.box .tip-box .content .title {
font-size: 18px;
line-height: 24px;
}
.box .tip-box .content .link {
padding: 16px 0 24px;
border-bottom: 1px solid #e5e6eb;
position: relative;
color: gray;
font-size: 14px;
}
.box .tip-box .content .btn {
display: block;
margin: 20px 0 24px auto;
color: #fff;
border-radius: 3px;
border: none;
background: #007fff;
height: 32px;
font-size: 14px;
padding: 0 14px;
cursor: pointer;
outline: 0;
}
</style>