Thực hành với Cổng: điều hướng liền mạch trên web

Tìm hiểu cách API Cổng vào được đề xuất có thể cải thiện trải nghiệm người dùng điều hướng của bạn.

Yusuke Utsunomiya
Yusuke Utsunomiya

Việc đảm bảo tải nhanh các trang là yếu tố then chốt để mang lại trải nghiệm tốt cho người dùng. Nhưng có một khía cạnh chúng tôi thường bỏ qua là hiệu ứng chuyển đổi trang — phần mà người dùng sẽ nhìn thấy khi chúng di chuyển giữa các trang.

Một đề xuất API nền tảng web mới có tên là Portals (Cổng thông tin) nhằm bằng cách đơn giản hoá trải nghiệm khi người dùng di chuyển trên của bạn.

Xem Cổng hoạt động trong thực tế:

nhúng và điều hướng liền mạch với Cổng vào. Do Adam Argyle tạo.

Những điều mà Cổng vào cho phép

Ứng dụng trang đơn (SPA) có những hiệu ứng chuyển cảnh đẹp nhưng đi kèm với chi phí xây dựng là độ phức tạp cao hơn. Ứng dụng nhiều trang (MPA) dễ xây dựng hơn nhiều, nhưng cuối cùng bạn lại có màn hình trống giữa các trang.

Cổng thông tin mang đến những lợi ích tốt nhất ở cả hai mặt: độ phức tạp thấp của MPA nhờ quá trình chuyển đổi liền mạch của SPA. Hãy nghĩ về các thành phần này như một <iframe> ở chỗ chúng cho phép nhúng, nhưng không giống như <iframe>, họ cũng có các tính năng để điều hướng đến nội dung của mình.

Thấy được niềm tin: trước tiên, hãy xem những nội dung chúng tôi đã trình bày tại Hội nghị Nhà phát triển Chrome 2018:

Với các thao tác cũ, người dùng phải đợi một màn hình trống cho đến khi trình duyệt hiển thị xong đích đến. Với Cổng vào, người dùng được trải nghiệm ảnh động, còn <portal> kết xuất trước nội dung và tạo trải nghiệm điều hướng liền mạch.

Trước khi Cổng thông tin, chúng ta có thể đã kết xuất một trang khác bằng cách sử dụng <iframe>. Chúng ta cũng có thể thêm ảnh động để di chuyển khung xung quanh trang. Tuy nhiên, <iframe> sẽ không cho phép bạn chuyển đến nội dung của ứng dụng đó. Cổng vào giúp thu hẹp khoảng cách này, cho phép các trường hợp sử dụng thú vị.

Dùng thử Portals

Bật thông qua about://flags

Dùng thử Cổng vào Chrome phiên bản 85 trở lên bằng cách lật cờ thử nghiệm:

  • Bật cờ about://flags/#enable-portals cho các thao tác điều hướng cùng nguồn gốc.
  • Để kiểm thử các thao tác điều hướng trên nhiều nguồn gốc, hãy bật thêm cờ about://flags/#enable-portals-cross-origin.

Trong giai đoạn đầu này của thử nghiệm Cổng thông tin, bạn cũng nên sử dụng một thư mục dữ liệu người dùng hoàn toàn riêng biệt cho các thử nghiệm của mình bằng cách thiết lập --user-data-dir cờ hiệu dòng lệnh. Sau khi bật Cổng, hãy xác nhận trong Công cụ cho nhà phát triển rằng bạn có HTMLPortalElement mới sáng bóng.

Ảnh chụp màn hình bảng điều khiển Công cụ cho nhà phát triển cho thấy HTMLPortalElement

Triển khai cổng thông tin

Hãy xem qua một ví dụ về cách triển khai cơ bản.

// Create a portal with the wikipedia page, and embed it
// (like an iframe). You can also use the <portal> tag instead.
portal = document.createElement('portal');
portal.src = 'https://en.wikipedia.org/wiki/World_Wide_Web';
portal.style = '...';
document.body.appendChild(portal);

// When the user touches the preview (embedded portal):
// do fancy animation, e.g. expand …
// and finish by doing the actual transition.
// For the sake of simplicity, this snippet will navigate
// on the `onload` event of the Portals element.
portal.addEventListener('load', (evt) => {
   portal.activate();
});

Thật đơn giản! Hãy thử mã này trong bảng điều khiển Công cụ cho nhà phát triển, trang wikipedia sẽ mở ra.

Ảnh GIF minh hoạ bản xem trước kiểu cổng thông tin

Nếu bạn muốn làm một công việc giống như bản minh hoạ ở trên, chúng tôi đã trình bày tại Hội nghị Nhà phát triển Chrome, bạn sẽ quan tâm đến đoạn mã sau.

// Adding some styles with transitions
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');
// Let's navigate into the WICG Portals spec page
portal.src = 'https://wicg.github.io/portals/';
// Add a class that defines the transition. Consider using
// `prefers-reduced-motion` media query to control the animation.
// https://developers.google.com/web/updates/2019/03/prefers-reduced-motion
portal.classList.add('portal-transition');
portal.addEventListener('click', (evt) => {
  // Animate the portal once user interacts
  portal.classList.add('portal-reveal');
});
portal.addEventListener('transitionend', (evt) => {
  if (evt.propertyName == 'transform') {
    // Activate the portal once the transition has completed
    portal.activate();
  }
});
document.body.append(style, portal);

Việc phát hiện tính năng để dần cải thiện trang web bằng Cổng thông tin cũng rất dễ dàng.

if ('HTMLPortalElement' in window) {
  // If this is a platform that have Portals...
  const portal = document.createElement('portal');
  ...
}

Nếu bạn muốn nhanh chóng trải nghiệm cảm giác của Cổng thông tin, hãy thử sử dụng uskay-portals-demo.glitch.me. Hãy đảm bảo bạn truy cập vào ứng dụng này bằng Chrome 85 trở lên và bật cờ thử nghiệm!

  1. Nhập URL bạn muốn xem trước.
  2. Sau đó, trang sẽ được nhúng dưới dạng một phần tử <portal>.
  3. Nhấp vào bản xem trước.
  4. Bản xem trước sẽ được kích hoạt sau một ảnh động.

Ảnh GIF minh hoạ lỗi trục trặc khi sử dụng Cổng

Xem thông số kỹ thuật

Chúng tôi đang tích cực thảo luận thông số kỹ thuật của Cổng thông tin trong Nhóm cộng đồng vườn ươm khởi nghiệp web (WICG). Để nhanh chóng làm quen với tốc độ, hãy xem một số các trường hợp chính. Dưới đây là ba tính năng quan trọng để bạn làm quen:

  • Phần tử <portal>: Chính phần tử HTML. API rất đơn giản. Giao diện này bao gồm thuộc tính src, hàm activate và một giao diện để nhắn tin (postMessage). activate lấy một đối số không bắt buộc để truyền dữ liệu đến <portal> khi kích hoạt.
  • Giao diện portalHost: Thêm đối tượng portalHost vào đối tượng window. Thao tác này giúp bạn kiểm tra xem trang có được nhúng dưới dạng phần tử <portal> hay không. Lớp này cũng cung cấp một giao diện để nhắn tin (postMessage) trở lại máy chủ.
  • Giao diện PortalKích hoạtEvent: Một sự kiện sẽ kích hoạt khi <portal> được kích hoạt. Có một hàm gọn gàng tên là adoptPredecessor mà bạn có thể dùng để truy xuất trang trước dưới dạng phần tử <portal>. Điều này cho phép bạn tạo các thao tác điều hướng và trải nghiệm liền mạch giữa hai trang.

Hãy cùng tìm hiểu bên ngoài mô hình sử dụng cơ bản. Dưới đây là danh sách chưa đầy đủ về những gì bạn có thể đạt được với Cổng cùng với mã mẫu.

Tuỳ chỉnh kiểu khi được nhúng dưới dạng phần tử <portal>

// Detect whether this page is hosted in a portal
if (window.portalHost) {
  // Customize the UI when being embedded as a portal
}

Nhắn tin giữa phần tử <portal>portalHost

// Send message to the portal element
const portal = document.querySelector('portal');
portal.postMessage({someKey: someValue}, ORIGIN);

// Receive message via window.portalHost
window.portalHost.addEventListener('message', (evt) => {
  const data = evt.data.someKey;
  // handle the event
});

Kích hoạt phần tử <portal> và nhận sự kiện portalactivate

// You can optionally add data to the argument of the activate function
portal.activate({data: {somekey: 'somevalue'}});

// The portal content will receive the portalactivate event
// when the activate happens
window.addEventListener('portalactivate', (evt) => {
  // Data available as evt.data
  const data = evt.data;
});

Truy xuất phiên bản tiền nhiệm

// Listen to the portalactivate event
window.addEventListener('portalactivate', (evt) => {
  // ... and creatively use the predecessor
  const portal = evt.adoptPredecessor();
  document.querySelector('someElm').appendChild(portal);
});

Biết rằng trang của bạn đã được sử dụng như phiên bản trước đó

// The activate function returns a Promise.
// When the promise resolves, it means that the portal has been activated.
// If this document was adopted by it, then window.portalHost will exist.
portal.activate().then(() => {
  // Check if this document was adopted into a portal element.
  if (window.portalHost) {
    // You can start communicating with the portal element
    // i.e. listen to messages
    window.portalHost.addEventListener('message', (evt) => {
      // handle the event
    });
  }
});

Bằng cách kết hợp tất cả các tính năng mà Cổng thông tin hỗ trợ, bạn có thể tạo ra những trải nghiệm người dùng thực sự thú vị. Ví dụ: bản minh hoạ bên dưới minh hoạ cách Cổng có thể mang lại trải nghiệm người dùng liền mạch giữa một trang web và nội dung được nhúng của bên thứ ba.

Trường hợp sử dụng và gói

Chúng tôi hy vọng bạn thích chuyến tham quan ngắn này về Cổng thông tin! Chúng tôi rất mong được thấy ý tưởng của bạn. Ví dụ: bạn có thể muốn bắt đầu sử dụng Cổng cho các điều hướng không quan trọng như: kết xuất trước trang cho sản phẩm bán chạy nhất của bạn từ trang danh sách danh mục sản phẩm.

Một điều quan trọng khác cần biết là Cổng có thể được dùng trong hoạt động điều hướng trên nhiều nguồn gốc, giống như <iframe>. Vì vậy, nếu có nhiều trang web tham chiếu chéo đến nhau, bạn cũng có thể sử dụng Cổng để tạo điều hướng liền mạch giữa hai trang web khác nhau. Trường hợp sử dụng trên nhiều nguồn gốc này rất riêng đối với Cổng thông tin, và thậm chí còn có thể cải thiện trải nghiệm người dùng cho các SPA.

Chúng tôi mong nhận được ý kiến phản hồi của bạn

Cổng thông tin đã sẵn sàng để thử nghiệm trong Chrome 85 trở lên. Phản hồi từ cộng đồng rất quan trọng đối với việc thiết kế các API mới, vì vậy hãy dùng thử và cho chúng tôi biết suy nghĩ của bạn! Nếu bạn có yêu cầu hoặc ý kiến phản hồi về tính năng, vui lòng chuyển đến kho lưu trữ GitHub của WICG.