做者 | Yusuke Utsunomiya译者 | 王强编辑 | 张之栋、王文婧想要了解新提案的 Portals API 是如何改善页面跳转用户体验的吗?本文将主要对 Portals 的具体内容、Portals 在 Chrome Canary 中的试用、Portals 的规范等几个方面进行详细讲解。若是你但愿用户在浏览自家网站时,可以在不一样页面跳转得更加流畅,不妨来读一读这篇文章。react
确保页面快速加载是提供良好用户体验的关键。可是咱们常常忽略的一个领域是页面过渡,也就是用户在页面之间移动时所看到的内容。git
一项名为 Portals 的 Web 平台 API 新提案,可让用户在浏览网站时提高不一样页面间跳转的流畅体验,从而帮助实现这一目标。github
如下连接中的视频展现了 Portals 的实际使用效果:https://storage.googleapis.com/web-dev-assets/hands-on-portals/portals_h264.mp4 web
Portals 带来了哪些内容单页应用程序(SPA)提供了很好的页面过渡效果,但代价是更高的构建复杂性。多页面应用程序(MPA)的构建更容易一些,但结果会致使页面之间跳转时屏幕显示空白内容。ajax
Portals 则取二者所长:同时具有 MPA 的低复杂性和 SPA 的无缝过渡效果。能够将它们视为一个<iframe>
,其中能够嵌入内容。但与<iframe>
不一样,它们还具备跳转到其中内容上的功能。chrome
眼见为实,请先来看看咱们去年在 Chrome 开发者峰会上展现的内容: https://youtu.be/Ai4aZ9Jbsysapi
使用经典跳转时,用户必须在等待时看着空白屏幕,直到浏览器渲染完目标页面为止。如今有了 Portals,用户能够在等待时体验到动画效果,而<portal>
会预渲染内容并建立出无缝的跳转体验。跨域
在 Portals 诞生以前,咱们可使用<iframe>
来预先渲染另外一个页面。咱们还能够添加动画在页面上移动这个 frame。可是<iframe>
不能让你跳转到其中的内容上。Portals 弥补了这一空白,从而能够实现一些有趣的用例。promise
要在 Chrome Canary 中试用 Portals,只需启用一个实验性标志: chrome://flags/#enable-portals浏览器
目前在 Portals 实验的早期阶段,咱们还建议设置 --user-data-dir命令行标志,使用彻底独立的用户数据目录进行测试。启用 Portals 后,在开发工具中确认你已经有了全新的 HTMLPortalElement。
// 用维基百科页面建立一个 portal,而后嵌入它。
// (就像一个 iframe)。你也可使用<portal>标志。
portal = document.createElement('portal');
portal.src = 'https://en.wikipedia.org/wiki/World_Wide_Web';
portal.style = '...';
document.body.appendChild(portal);
// 用户触碰预览时(嵌入的 portal):
// 播放漂亮的动画,例如展开……
// 实际跳转完成后动画结束。
portal.activate();
就这么简单。在开发工具控制台中尝试这段代码,应该会打开维基百科页面。
// 添加一些过渡样式功能检测也很容易,这样就可使用 Portals 对网站进行渐进式加强。
const style = document.createElement('style');
style.innerHTML = `
portal {
position:fixed;
width: 100%;
height: 100%;
opacity: 0;
box-shadow: 0 0 20px 10px #999;
transform: scale(0.4);
transform-origin: bottom left;
bottom: 20px;
left: 20px;
animation-name: fade-in;
animation-duration: 1s;
animation-delay: 2s;
animation-fill-mode: forwards;
}
.portal-transition {
transition: transform 0.4s;
}
@media (prefers-reduced-motion: reduce) {
.portal-transition {
transition: transform 0.001s;
}
}
.portal-reveal {
transform: scale(1.0) translateX(-20px) translateY(20px);
}
@keyframes fade-in {
0% { opacity: 0; }
100% { opacity: 1; }
}
`;
const portal = document.createElement('portal');
// 跳转到 WICG Portals spec 页面
portal.src = 'https://wicg.github.io/portals/';
// 添加一个定义了过渡效果的类。考虑使用
// `prefers-reduced-motion` media query 来控制动画。
// https://developers.google.com/web/updates/2019/03/prefers-reduced-motion
portal.classList.add('portal-transition');
portal.addEventListener('click', evt => {
// 用户交互时显示 portal 的动画
portal.classList.add('portal-reveal');
});
portal.addEventListener('transitionend', evt => {
if (evt.propertyName == 'transform') {
// 过渡效果完成时激活这个 portal
portal.activate();
}
});
document.body.append(style, portal);
if ('HTMLPortalElement' in window) {若是你想快速体验 Portal 的感受,请试试 uskay-portals-demo.glitch.me。请使用 Chrome Canary 访问它并打开实验性标志!
// 若是这个平台有 Portals……
const portal = document.createElement('portal');
...
}
<portal>
元素嵌入。动画播放后将激活预览。
<portal>
元素:HTML 元素自己。该 API 很是简单。它由 src 属性、activate 函数和消息传递接口(postMessage)组成。activate 带有一个可选参数,以在激活时将数据传递给<portal>
。<portal>
元素嵌入。它还提供了用于将消息传递(postMessage)返回主机的接口。PortalActivateEvent接口:激活<portal>
时将触发的事件。有一个整洁的函数,名为 adoptPredecessor,你能够用它将上一页做为一个<portal>
元素取回。这使你能够在两个页面之间建立无缝跳转和组合式体验。
下面看看基本使用模式之外的内容。如下是 Portals 能够实现的内容详细列表及示例代码。
当嵌入为元素时自定义样式
// 检查该页面是否由一个 portal 托管
if (window.portalHost) {
// 嵌入为 portal 时自定义 UI
}
元素和 portalHost 之间的消息传递
// 向 portal 元素发送消息
const portal = document.querySelector('portal');
portal.postMessage({someKey: someValue}, ORIGIN);
// 经过 window.portalHost 接收消息
window.portalHost.addEventListener('message', evt => {
const data = evt.data.someKey;
// 处理事件
});
激活元素并接收 portalactivate 事件
// 你能够选择向激活函数的参数添加数据
portal.activate({data: {'somekey': 'somevalue'}});
// 激活时 portal 内容会接收 portalactivate 事件
window.addEventListener('portalactivate', evt => {
// 数据做为 evt.data 可用
const data = evt.data;
});
获取前页
// 侦听 portalactivate 事件
window.addEventListener('portalactivate', evt => {
// ……创新地使用前页
const portal = evt.adoptPredecessor();
document.querySelector('someElm').appendChild(portal);
});
知道你的页面已被视为前页
// 激活函数返回一个 Promise.
// 当 promise 解析时, 意味着 portal 已被激活。
// 若是该文档被其采用,则会存在 window.portalHost。
portal.activate().then(_ => {
// 检查该文档是否被 portal 元素采纳。
if (window.portalHost) {
// 能够开始与 portal 元素通讯
// 如侦听消息
window.portalHost.addEventListener('message', evt => {
// 处理事件
});
}
});
经过组合 Portals 支持的全部这些功能,你能够构建很是精美的用户体验。例如,下面演示了 Portal 如何在网站和第三方嵌入内容之间实现无缝的用户体验: https://youtu.be/4JkipxFVE9k
对这个演示感兴趣吗?能够在 GitHub 上 fork 它,并构建你本身的版本: https://github.com/WICG/portals/tree/master/demos/portal-embed-demo
用例和计划咱们但愿你喜欢这篇关于 Portals 的简短介绍!咱们火烧眉毛想看看你们能作出些什么内容。你可能想要开始使用 Portals 进行很是规跳转,好比,从产品类别列表页面中预渲染最畅销产品页面。
另外一件重要的事情是,Portals 能够像<iframe>
同样用于跨域跳转。所以,若是你有多个相互交叉引用的网站,还可使用 Portals 在两个不一样的网站之间建立无缝跳转。这是 Portals 的独特用例,甚至能够改善 SPA 的用户体验。
Portals 提案仍处于早期阶段,所以并不是一切都能正常工做(这就是它位于实验性标志后的缘由)。也就是说,它已准备好在 Chrome Canary 中进行实验。社区的反馈对于新 API 的设计相当重要,所以请尝试一下,并告诉咱们你的想法!你能够在 Chromium 错误跟踪器上检查当前的限制条件。若是你有任何功能要求或反馈,请转到 WICG GitHub 仓库: https://github.com/WICG/portals/issues
原文连接:
https://web.dev/hands-on-portals/阅读 4342分享收藏赞在看23写下你的留言精选留言。°Ler2多年前用uc有一个鼠标悬停预览的功能,悬停某个连接就会出现和这个同样的功能。firegnu1一楼的那是早期ajax的实现.:D1谷歌666哦~Brandonxiang1支持,但愿全部浏览器跟进Xheldon