同源页面通信在网页登录方面的应用

为什么一个“普普通通”的网页登录要和“看似高大上”的同源页面通信联系了起来?

可能你没有发现:往往如果你的登录页是从主页通过 window.open()js-href 另打开的一个tab,在你登录成功后,要么是重新打开一个主页的tab,要么就要你回到原主页tab刷新一下才可。
可是这简简单单的“刷新”或“关闭原主页tab”带来的却是“用户体验”的低水平。如果我们能在登录后返回主页面时“自动同步信息”,会不会更好一点?事实上,比如「字节跳动(招聘)官网」就是这么做的!

还有不少网页干脆把两个页面设置为“同tab跳转”(非PWA框架)

那么要完成这么一件事,要怎么做呢?


① Page Visibility(页面可见性)API

众所周知,CSS中有一个很讨人喜欢的属性:visibility: hidden/visible; ,巧的是:hidden 和visible 同样是此 API 的两个状态值。它的属性和事件如下:

  • document.hidden :true/false,表示当前页面不可见/可见;
  • document.visibilityState :当前页面可见状态 —— hidden / visible / prerender / preview ;
  • visibilitychange :可见状态变化时触发的事件

这个 API 只负责“切换”,那和“登录同步”又有什么关系?其实它主要利用了“ 同源页面间localStorage共享 ”的原理。代码如下:

主页

<p id="loginInfo">p>

这里由于涉及到不同浏览器之间的差异性以及使用的不同,建议使用时直接引入张鑫旭大神封装好的在线js文件:

// 引入
<script src="https://www.zhangxinxu.com/study/201211/pageVisibility.js"></script>
<script type="text/javascript">(function() {if (typeof pageVisibility.hidden !== "undefined") {   // 张大神的源码中这里表现为是否支持visibility APIvar eleLoginInfo = document.querySelector("#loginInfo");var funLoginInfo = function() {var username = localStorage.username || sessionStorage.username;if (username) {eleLoginInfo.innerHTML = '欢迎回来,' + username + '';sessionStorage.username = username;} else {eleLoginInfo.innerHTML = '您尚未登录,请登录';}    }// 触发事件pageVisibility.visibilitychange(function() {if (!this.hidden) funLoginInfo();});funLoginInfo();// 页面关闭清除localStoragewindow.addEventListener("unload", function() {localStorage.removeItem("username");})} else {alert("你的这个浏览器不支持Page Visibility API的啦!");    }})();
</script>

登录页

<div class="boxs"><form id="loginForm" action="" method="post"><p>用户名:<input type="text" name="username" required />p><p>密码:<input type="password" name="password" required />p><p><input type="submit" />p>form>
div>
(function() {if (typeof window.screenX === "number") {var eleLoginForm = document.querySelector("#loginForm");eleLoginForm.addEventListener("submit", function(e) {localStorage.username = document.querySelector("input[name='username']").value;alert("登录成功!现在可以回到刚才的页面了!");this.reset();e.preventDefault();}, false);} else {alert("抱歉!您的浏览器连H5表单都不支持!");    }
})();

link-img

目前来说,这个API尤其在移动端实际效果太差,使用与否,就看各自需求了…


② BroadCast Channel

你可以认为它对 postMessage 做了封装。它可以帮我们创建一个用于广播的通信频道,当几个页面都监听了同一个频道的消息时,其中某一个页面通过此 API 发送的消息就会被其它页面收到。

它的使用方式你可能会感到熟悉:

// 创建带有标识的频道
const bc=new BroadCastChannel('yxm')

它甚至可以接收一个 DOMString 作为name标识,在其它页面可用通过传入相同的name(bc.name)使用同一个广播频道。

// 发送消息
bc.postMessage(这里可以是字符串,也可以是变量名)

↑ 你完全可以在登录成功后的回调中将用户名传入

// 监听消息
bc.onmessage=function(e){// 通过 e.data 取数据
}
bc.onmessageerror=function(e){// 通过 e 捕获错误
}

除此之外,你当然也可以用 addEventListener 添加 message 监听。

// 关闭
bc.close()

除了上面说的两种,在“原生API”下还有比如 websocket 、server sent 这样的API:他们可以和服务器建立通道,一定程度上避免了“轮询”带来的消耗,非常nice!


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部