Ba hiểu biết tôi đạt được khi nghiên cứu về khả năng truy cập của Vue.js

theanh

Administrator
Nhân viên
Các khuôn khổ JavaScript như React, Angular và Vue có tiếng xấu khi nói đến khả năng truy cập web. Nhưng điều này là do những hạn chế kỹ thuật cố hữu hay các vấn đề không thể khắc phục của các công cụ đó? Tôi nghĩ là không. Trong giai đoạn nghiên cứu của cuốn sách "Accessible Vue", tôi đã có được ba hiểu biết sâu sắc về khả năng truy cập ứng dụng web nói chung và khuôn khổ nói riêng. Xem xét những điều này, có lẽ chúng ta nên có một góc nhìn khác về các ứng dụng Vue có thể truy cập.

Hiểu biết sâu sắc 1: Các tính năng của khuôn khổ JavaScript dành cho khả năng truy cập đang bị sử dụng ít​

Thiết kế dựa trên thành phần, được kích hoạt và thực thi bởi các khuôn khổ JavaScript hiện đại, không chỉ mang lại trải nghiệm tuyệt vời cho nhà phát triển và tính công thái học của dự án khi được sử dụng một cách thông minh mà còn có thể mang lại lợi thế về khả năng truy cập. Đầu tiên là yếu tố tái sử dụng, tức là khi thành phần của bạn được sử dụng ở nhiều nơi trong ứng dụng của bạn (có thể ở nhiều dạng hoặc hình dạng khác nhau) và chỉ cần tạo khả năng truy cập một lần. Trong trường hợp này, trải nghiệm của nhà phát triển được cải thiện thực sự giúp ích cho người dùng và "đưa khả năng truy cập vào các thành phần" (như Hidde de Vries nói) tạo ra một viễn cảnh đôi bên cùng có lợi cho tất cả mọi người.

Khía cạnh thứ hai đi kèm với thiết kế dựa trên thành phần là props — cụ thể là ở dạng mà một thành phần có thể kế thừa hoặc lấy ngữ cảnh từ môi trường cha của nó. Việc chuyển tiếp "dữ liệu môi trường" này cũng có thể phục vụ cho khả năng truy cập.

Lấy tiêu đề làm ví dụ. Cấu trúc tiêu đề vững chắc và dễ hiểu không chỉ tốt cho SEO mà còn đặc biệt tốt cho những người sử dụng trình đọc màn hình. Khi họ gặp một dàn ý tài liệu hợp lý, được xây dựng bằng các tiêu đề cấu trúc nên trang web hoặc ứng dụng, người dùng trình đọc màn hình sẽ có được cái nhìn tổng quan nhanh về trang web họ đang xem. Giống như người dùng có thị lực không đọc từng từ trên trang mà chỉ quét để tìm những điều thú vị, người dùng trình đọc màn hình khiếm thị không yêu cầu phần mềm của họ đọc từng từ. Thay vào đó, họ đang kiểm tra tài liệu để tìm nội dung và chức năng mà họ quan tâm. Về vấn đề này, tiêu đề giữ các phần nội dung lại với nhau và đồng thời cung cấp một khung cấu trúc cho tài liệu (hãy nghĩ đến những ngôi nhà khung gỗ).

Điều khiến tiêu đề cung cấp một cấu trúc không chỉ là sự tồn tại đơn thuần của chúng. Đó cũng là cách chúng lồng vào nhau tạo nên hình ảnh trong tâm trí người dùng. Để làm được điều đó, hộp công cụ tiêu đề của nhà phát triển web chứa sáu cấp độ ([HEADING=1] đến ). Bằng cách áp dụng các cấp độ này, cả biên tập viên và nhà phát triển đều có thể tạo ra một phác thảo nội dung và chức năng đáng tin cậy mà người dùng có thể mong đợi trong tài liệu.

Ví dụ, hãy lấy cây tiêu đề (đã rút gọn) từ trang web GOV.UK:
Mã:
1 — Chào mừng đến với GOV.UK 2 — Phổ biến trên GOV.UK 2 — Dịch vụ và thông tin 3 — Quyền lợi 3 — Sinh, tử, kết hôn và chăm sóc 3 — Kinh doanh và tự kinh doanh // …v.v. 2 — Các phòng ban và chính sách 3 — Virus Corona (COVID 19) 3 — Du lịch nước ngoài: từng bước…v.v.
Ngay cả khi không truy cập trang thực tế và không thực sự nhận thức trực quan, cây tiêu đề này đã tạo ra một mục lục giúp bạn hiểu những phần nào có thể được mong đợi trên trang đầu. Những người sáng tạo đã sử dụng các phần tử tiêu đề để báo hiệu dữ liệu theo sau nó và không bỏ qua các cấp tiêu đề.

Cho đến nay, khá quen thuộc (ít nhất là khi so sánh với các công cụ tìm kiếm, tôi đoán vậy). Tuy nhiên, vì một thành phần có thể được sử dụng ở nhiều nơi khác nhau trong ứng dụng của bạn, nên các cấp tiêu đề được lập trình sẵn bên trong chúng đôi khi có thể tạo ra một cây tiêu đề không tối ưu nhìn chung. Mối quan hệ giữa các tiêu đề có thể không được truyền đạt rõ ràng như trong ví dụ trên ("Kinh doanh và tự kinh doanh" không tồn tại độc lập mà liên quan đến "Dịch vụ và thông tin").

Ví dụ, hãy tưởng tượng danh sách các sản phẩm mới nhất của một cửa hàng có thể được đặt trong cả nội dung chính và thanh bên — rất có thể cả hai phần đều nằm trong các bối cảnh khác nhau. Tiêu đề như Sản phẩm mới nhất của chúng tôi[/HEADING] sẽ hợp lý hơn khi đặt ở phía trên danh sách sản phẩm trong nội dung chính — vì đây là nội dung trung tâm của toàn bộ tài liệu hoặc chế độ xem.

Cùng một thành phần có cùng [HEADING=1] nhưng được đặt trong thanh bên của một tài liệu khác, tuy nhiên, sẽ gợi ý rằng nội dung quan trọng nhất nằm trong thanh bên và cạnh tranh với trong nội dung chính. Mặc dù những gì tôi mô tả ở trên là một đặc điểm chung của thiết kế dựa trên thành phần, nhưng điều này mang đến cho chúng ta cơ hội hoàn hảo để kết hợp cả hai khía cạnh lại với nhau — nhu cầu về một cây tiêu đề hợp lý và kiến thức của chúng ta về đạo cụ:

Context Via props

Chúng ta hãy tiến từ các cân nhắc lý thuyết đến mã thực hành. Trong khối mã sau, bạn thấy một thành phần liệt kê các vấn đề mới nhất trong một cửa hàng trực tuyến. Nó cực kỳ đơn giản nhưng trọng tâm là dòng 3, được mã hóa cứng:
Mã:
  Những sản phẩm mới nhất của chúng tôi[/HEADING] [LIST=1] 
[*] Sản phẩm A 
[*] Sản phẩm B  [/LIST]
Để sử dụng thành phần này ở những nơi khác nhau của ứng dụng mà không ảnh hưởng đến cây tiêu đề của tài liệu, chúng tôi muốn làm cho cấp tiêu đề trở nên động. Để đạt được điều này, chúng ta thay thế bằng trình trợ giúp tên thành phần động của Vue được gọi là thành phần:
Mã:
Những sản phẩm mới nhất của chúng tôi
Trong phần tập lệnh của thành phần, giờ đây chúng ta phải thêm hai thứ:
  • Một prop thành phần nhận mức tiêu đề chính xác dưới dạng chuỗi, headlineLevel;
  • Một thuộc tính được tính toán (headlineElement từ ví dụ mã ở trên) xây dựng một phần tử HTML phù hợp từ chuỗi h và giá trị của headlineLevel.
Vì vậy, khối tập lệnh được đơn giản hóa của chúng ta trông như thế này:
Mã:
export default { props: { headlineLevel: { type: String }, computed: { headlineElement() { return "h" + this.headlineLevel; } }}
Và thế là xong!

Tất nhiên, việc thêm các kiểm tra và mặc định hợp lý vào cấp độ prop là cần thiết — ví dụ, chúng ta phải đảm bảo rằng headlineLevel chỉ có thể là một số từ 1 đến 6. Cả Prop Validation gốc của Vue cũng như TypeScript đều là những công cụ bạn có thể sử dụng để thực hiện điều đó, nhưng tôi muốn giữ nó ngoài ví dụ này.

Nếu bạn tình cờ muốn tìm hiểu cách thực hiện chính xác khái niệm tương tự bằng React, người bạn của tạp chí show Heydon Pickering đã viết về chủ đề này vào 2018 và cung cấp mã mẫu React/JSX. Các thành phần Heading của Tenon UI, cũng được viết cho React, đưa khái niệm này đi xa hơn nữa và hướng đến mục tiêu tự động hóa việc tạo cấp tiêu đề bằng cách sử dụng cái gọi là "LevelBoundaries" và một phần tử chung. Hãy xem!

Thông tin chi tiết 2: Có những chiến lược đã được thiết lập để giải quyết các vấn đề về khả năng truy cập của ứng dụng web​

Mặc dù khả năng truy cập của ứng dụng web có vẻ đáng sợ khi bạn lần đầu tiên gặp chủ đề này, nhưng không cần phải tuyệt vọng: các mẫu khả năng truy cập được trao quyền để giải quyết các đặc điểm thông thường của ứng dụng web thực sự tồn tại. Trong phần Insight sau đây, tôi sẽ giới thiệu cho bạn các chiến lược cung cấp thông báo có thể truy cập, bao gồm triển khai dễ dàng trong Vue.js (Chiến lược 1), sau đó chỉ cho bạn các mẫu được đề xuất và các mẫu tương ứng trong Vue (Chiến lược 2). Cuối cùng, tôi khuyên bạn nên xem xét cả chiến lược mới nổi của Vue (Chiến lược 3) và cộng đồng trợ năng đã thành lập của React (Chiến lược 4).

Chiến lược 1: Công bố các bản cập nhật động với Live Regions​

Mặc dù trợ năng không chỉ là làm cho mọi thứ tương thích với trình đọc màn hình, nhưng việc cải thiện trải nghiệm trình đọc màn hình đóng vai trò quan trọng trong khả năng truy cập của ứng dụng web. Điều này bắt nguồn từ nguyên tắc hoạt động chung của dạng công nghệ hỗ trợ này: phần mềm trình đọc màn hình chuyển đổi nội dung trên màn hình thành đầu ra âm thanh hoặc chữ nổi, do đó cho phép người khiếm thị tương tác với web và công nghệ nói chung.

Giống như tiêu điểm bàn phím, điểm đầu ra của trình đọc màn hình, cái gọi là con trỏ ảo, chỉ có thể ở một nơi tại một thời điểm. Đồng thời, một khía cạnh cốt lõi của ứng dụng web là thay đổi động trong các phần của tài liệu mà không cần tải lại trang. Nhưng điều gì xảy ra, ví dụ, khi bản cập nhật trong DOM thực sự ở trên vị trí của con trỏ ảo trong tài liệu? Người dùng có thể sẽ không nhận thấy sự thay đổi vì không có xu hướng duyệt tài liệu theo chiều ngược lại — trừ khi họ được thông báo về bản cập nhật động.

Trong video ngắn sau, tôi sẽ trình bày những gì xảy ra (hay đúng hơn là những gì không xảy ra) nếu một tương tác gây ra thay đổi DOM động không ở gần con trỏ ảo — trình đọc màn hình chỉ im lặng:

[*]
Nhưng bằng cách sử dụng ARIA Live Regions, các nhà phát triển web có thể kích hoạt các thông báo có thể truy cập được, cụ thể là đầu ra của trình đọc màn hình độc lập với vị trí của con trỏ ảo. Cách thức hoạt động của các vùng trực tiếp là trình đọc màn hình được hướng dẫn quan sát một số phần tử HTML textContent. Khi thay đổi do tập lệnh, trình đọc màn hình sẽ chọn bản cập nhật và văn bản mới sẽ được đọc ra.

Ví dụ, hãy tưởng tượng một danh sách các sản phẩm trong một cửa hàng trực tuyến. Các sản phẩm được liệt kê trong một bảng và người dùng có thể thêm mọi sản phẩm vào giỏ hàng của họ mà không cần tải lại trang chỉ bằng một cú nhấp chuột. Bản cập nhật không đồng bộ dự kiến của DOM, mặc dù có thể nhận thấy đối với người dùng trực quan, nhưng là một công việc hoàn hảo cho các vùng trực tiếp.

Hãy viết một đoạn mã mơ ước được đơn giản hóa cho tình huống này. Đây là HTML:
Mã:
Add to cart
Bây giờ, cả bản cập nhật DOM và thông báo vùng trực tiếp đều chỉ có thể thực hiện được bằng JavaScript. Vì vậy, hãy xem phần tập lệnh được đơn giản hóa tương tự của trình xử lý nhấp vào nút "Thêm vào giỏ hàng" của chúng tôi:
Mã:
const buttonAddProductOneToCart = document.getElementById('addToCartOne');const liveRegion = document.getElementById('info');buttonAddProductOneToCart.addEventListener('click', () => { // Phép thuật thêm logic thực tế 🪄 // Kích hoạt vùng trực tiếp: liveRegion.textContent = "Sản phẩm One đã được thêm vào giỏ hàng của bạn";});
Bạn có thể thấy trong mã ở trên rằng khi việc thêm thực tế diễn ra (tất nhiên, việc triển khai thực tế phụ thuộc vào nguồn dữ liệu và ngăn xếp công nghệ của bạn), một thông báo có thể truy cập được kích hoạt. từng trống với ID là info sẽ thay đổi nội dung văn bản của nó thành "Sản phẩm Một đã được thêm vào giỏ hàng của bạn". Vì trình đọc màn hình quan sát vùng để biết những thay đổi như thế này, nên đầu ra của trình đọc màn hình bất kể vị trí con trỏ ảo là gì sẽ được nhắc. Và vì vùng trực tiếp được đặt thành lịch sự, nên thông báo sẽ chờ trong trường hợp có đầu ra hiện tại.

Nếu bạn thực sự muốn truyền tải một thông báo quan trọng mà không tôn trọng thông báo của trình đọc màn hình hiện tại nhưng lại ngắt thông báo đó, thì thuộc tính aria-live cũng có thể được đặt thành khẳng định. Bản thân Live regions là những công cụ mạnh mẽ cần được sử dụng thận trọng, điều này thậm chí còn đúng hơn đối với loại "hung hăng" hơn này. Vì vậy, hãy giới hạn việc sử dụng chúng cho các thông báo lỗi khẩn cấp mà người dùng phải biết, ví dụ: "Tự động lưu không thành công, vui lòng lưu thủ công".

Chúng ta hãy xem lại ví dụ ở trên, lần này với các live regions đã triển khai: Người dùng trình đọc màn hình hiện được thông báo rằng tương tác nút của họ đã hoạt động và mặt hàng cụ thể đã được thêm vào (hoặc xóa khỏi) giỏ hàng của họ:

Nếu bạn muốn sử dụng live regions trong các ứng dụng Vue.js, tất nhiên, bạn có thể tạo lại các ví dụ mã ở trên. Tuy nhiên, một cách dễ hơn là sử dụng thư viện vue-announcer. Sau khi cài đặt bằng npm install -S @vue-a11y/announcer (hoặc npm install -S @vue-a11y/announcer@next cho phiên bản Vue 3) và đăng ký nó thành plugin Vue, chỉ cần thực hiện hai bước sau:
  1. Vị trí của trong mẫu App.vue của bạn. Điều này sẽ tạo ra một vùng trực tiếp trống (giống như vùng ở trên có ID là info).
    Lưu ý: Bạn chỉ nên sử dụng một phiên bản vùng trực tiếp và việc đặt nó ở một vị trí trung tâm là hợp lý để nhiều thành phần có thể tham chiếu đến nó.
Mã:
  1. Kích hoạt vùng trực tiếp, ví dụ như từ bên trong một phương thức hoặc móc vòng đời. Cách dễ nhất để thực hiện điều này là sử dụng phương thức .set hoặc this.$announcer. Tham số đầu tiên của phương thức là văn bản mà vùng trực tiếp được cập nhật (tương đương với văn bản mà trình đọc màn hình sẽ xuất ra). Là tham số thứ hai, bạn có thể cung cấp rõ ràng politeassertive làm cài đặt). Tuy nhiên, như bạn sẽ thấy, đây là tùy chọn — trong trường hợp tham số bị bỏ qua, thông báo sẽ là thông báo lịch sự:
Mã:
methods: { addProductToCart(product) { // Logic thêm thực tế tại đây this.$announcer.set(`${product.title} has been added to your cart.`); }}
Đây chỉ là một cái nhìn thoáng qua về thế giới tuyệt vời của vùng trực tiếp ARIA. Trên thực tế, có nhiều tùy chọn hơn là polite và assert (chẳng hạn như log, timer và thậm chí là marquee) nhưng có nhiều hỗ trợ khác nhau trong trình đọc màn hình.

Nếu bạn muốn tìm hiểu sâu hơn về chủ đề này, đây là ba tài nguyên được đề xuất:
  • ARIA Live Regions,” MDN Web Docs
  • The Many Lives Of A Notification,” Sarah Higley (video)
  • NerdeRegion, một tiện ích mở rộng của Chrome cho phép bạn mô phỏng sơ bộ đầu ra vùng trực tiếp trong các công cụ phát triển của bạn mà không cần phải khởi động trình đọc màn hình. Tuy nhiên, điều này không nên thay thế việc thử nghiệm có lương tâm trong trình đọc màn hình thực!

Chiến lược 2: Sử dụng các Thực hành biên soạn WAI-ARIA không thể tranh cãi​

Khoảnh khắc bạn gặp phải các thực hành biên soạn của WAI-ARIA, bạn có thể sẽ cảm thấy nhẹ nhõm rất nhiều. Có vẻ như tổ chức chuẩn của web, W3 Consortium, cung cấp một số loại thư viện mẫu mà bạn chỉ cần sử dụng (hoặc chuyển đổi sang khuôn khổ bạn chọn) và thế là, mọi thách thức về khả năng truy cập ứng dụng web của bạn đều được giải quyết.

Tuy nhiên, thực tế không đơn giản như vậy. Mặc dù W3C cung cấp rất nhiều mẫu ứng dụng web thông thường như hộp kết hợp, thanh trượt, menu và chế độ xem cây, nhưng không phải tất cả các thực hành biên soạn đều ở trạng thái được khuyến nghị cho sản xuất. Ý tưởng thực sự đằng sau các thực hành biên soạn là để chứng minh việc sử dụng "thuần túy" các trạng thái ARIA, vai trò và mẫu tiện ích.

Nhưng để trở thành một mẫu thực sự được kiểm tra, tác giả của nó phải đảm bảo rằng mọi thực hành đều có sự hỗ trợ vững chắc giữa các công nghệ hỗ trợ và cũng hoạt động liền mạch cho các thiết bị cảm ứng. Than ôi, đó là nơi mà một số mẫu được liệt kê trong Thực hành biên soạn không đạt yêu cầu. Phát triển web đang trong tình trạng thay đổi liên tục và có khả năng sự phát triển của ứng dụng web thậm chí còn hơn thế nữa. Một nơi tốt để cập nhật tình trạng của các thực hành biên soạn đơn lẻ là kho authoring-practices trên GitHub của W3C. Trong phần Issues, các chuyên gia về khả năng truy cập web trao đổi ý tưởng, kinh nghiệm và nghiên cứu thử nghiệm hiện tại của họ cho mọi mẫu.

Tuy nhiên, tất cả những điều đó không có nghĩa là các thực hành không có giá trị gì đối với các dự án khả năng truy cập ứng dụng web của bạn. Mặc dù có những tiện ích chỉ là bằng chứng về khái niệm, nhưng vẫn có những mẫu vững chắc. Sau đây, tôi muốn nêu bật ba Thực hành biên soạn không thể tranh cãi và các đối tác của chúng trong Vue.js tích hợp:

  • Tiện ích Disclosure là những khái niệm đơn giản và dễ hiểu có thể được sử dụng theo nhiều cách khác nhau: làm cơ sở cho accordion có thể truy cập của bạn, làm một phần của menu điều hướng thả xuống mạnh mẽ hoặc để hiển thị và ẩn thông tin bổ sung, như mô tả hình ảnh mở rộng.

    Điều tuyệt vời về mẫu này là nó chỉ bao gồm hai phần tử: Một trình kích hoạt (1) bật/tắt chế độ hiển thị của vùng chứa (2). Theo thuật ngữ HTML, trình kích hoạt và vùng chứa phải theo sau nhau trực tiếp trong DOM. Để tìm hiểu thêm về khái niệm và cách triển khai trong Vue, hãy đọc bài viết trên blog của tôi về Tiện ích Disclosure trong Vue hoặc xem bản demo tương ứng trên CodeSandBox.

  • Hộp thoại dạng hộp thoại cũng được coi là một mẫu đã thiết lập. Điều khiến hộp thoại trở thành "hộp thoại" là thuộc tính của nó để hiển thị các phần của giao diện không phải là nội dung của hộp thoại không hoạt động khi hộp thoại mở.

    Hơn nữa, các nhà phát triển phải đảm bảo rằng tiêu điểm bàn phím được gửi vào hộp thoại khi kích hoạt, không thể rời khỏi hộp thoại mở và được gửi trở lại điều khiển kích hoạt sau khi hủy kích hoạt. Thành phần A11y Dialog của Kitty Giraudel sẽ xử lý tất cả những điều tôi vừa mô tả. Đối với các nhà phát triển sử dụng Vue.js, có một plugin có tên là vue-a11y-dialog.

  • Thành phần Tab là một mẫu động phổ biến hoạt động với phép ẩn dụ về các tab thư mục vật lý và do đó, giúp tác giả đóng gói lượng nội dung lớn hơn vào "bảng tab". Thực hành biên soạn có hai biến thể liên quan đến kích hoạt bảng điều khiển (tự động hoặc thủ công).

    Điều quan trọng hơn nữa là các thành phần tab được hỗ trợ tốt trong công nghệ hỗ trợ và do đó có thể được coi là một mô hình được khuyến nghị (miễn là bạn kiểm tra chế độ kích hoạt nào phù hợp nhất với người dùng của mình). Về mặt kiến trúc, có nhiều cách để xây dựng thành phần tab với sự trợ giúp của Vue.js: Trong CodeSandBox này, tôi quyết định sử dụng phương pháp dựa trên khe cắm và kích hoạt tự động.

Chiến lược 3: Xem và giúp các sáng kiến về khả năng truy cập của Vue phát triển​

Mặc dù vẫn còn một chặng đường dài phía trước, nhưng có thể khẳng định rằng chủ đề về khả năng truy cập trong Vue.js cuối cùng cũng đang trên đà phát triển. Một cột mốc quan trọng cho chủ đề này là việc bổ sung phần "Trợ năng" vào tài liệu chính thức của Vue, liên quan đến việc phát hành Vue 3.

Nhưng ngay cả khi không có các tài nguyên chính thức, những người sau đây trong cộng đồng Vue cũng đáng để theo dõi vì họ cung cấp tài liệu giáo dục, thành phần trợ năng hoặc cả hai:
  • Maria Lombardo có tư cách là "đối tác cộng đồng Vue", là người viết tài liệu về khả năng truy cập được liên kết ở trên, đang tổ chức các hội thảo liên quan đến a11y tại các hội nghị Vue và có khóa học Cơ bản về khả năng truy cập web (có trả phí) tại vueschool.io.
  • Một bài viết về khả năng truy cập trong Vue.js sẽ không trọn vẹn nếu không nhắc đến Alan Ktquez, trưởng dự án của vue-a11y.com. Anh ấy và sáng kiến cộng đồng của anh ấy tạo ra và duy trì các plugin như vue-announcer đã đề cập ở trên, vue-skipto để tạo liên kết bỏ qua, vue-axe như một trình bao bọc Vue xung quanh công cụ kiểm tra axe-core của Deque và đặc biệt là awesome-vue-a11y, một danh sách liên kết ngày càng mở rộng của các tài nguyên trợ năng trong Vueniverse.
  • Người đồng hương Berlin Oscar Braunert đặc biệt tập trung vào các đầu vào bao gồm và chỉ ra cách triển khai chúng trong Vue.js, ví dụ dưới dạng bài nói chuyệnbài viết. Với thư viện UI tournant, Oscar và tôi đang hướng đến mục tiêu cung cấp các thành phần có thể truy cập được dựa trên (không thể tranh cãi) WAI Authoring Practices (xem Chiến lược 2) và Inclusive Components của Heydon Pickering.
  • Moritz Kröger đã xây dựng một trình bao bọc Vue cho a11y-dialog của Kitty Giraudel được gọi là vue-a11y-dialog, cung cấp mọi thứ mà một nhà phát triển cần về mặt ngữ nghĩa và quản lý tiêu điểm (xem ở trên).

Chiến lược 4: Học hỏi từ React Accessibility Leads​

Nếu bạn so sánh nó với con chó đầu đàn React.js, Vue.js không phải là sản phẩm ngách, nhưng bạn phải thừa nhận rằng nó đã (chưa?) đạt được mức độ phổ biến của mình. Tuy nhiên, điều này không nhất thiết phải là một bất lợi khi nói đến khả năng truy cập. React — và Angular trước đó — theo một nghĩa nào đó là tiên phong trong khả năng truy cập chỉ bằng sự phổ biến của chúng.

Các khuôn khổ càng trở nên phổ biến thì khả năng công việc tốt về mặt bao hàm càng cao. Có thể là do các sáng kiến cộng đồng về chủ đề này hoặc đơn giản là các cơ quan chính phủ có nghĩa vụ về khả năng truy cập web thực hiện "mua vào". Nếu họ cũng chia sẻ các phát hiện và mã có thể truy cập của mình thông qua nguồn mở, thì đó là tình huống có lợi cho cả ba bên. Không chỉ đối với bản thân khuôn khổ và cộng đồng của nó mà còn đối với "các đối thủ cạnh tranh".

Điều này thực sự đã xảy ra trong trường hợp của React (và dự án của chính phủ mà tôi đã nói đến một cách trừu tượng là Hệ thống thiết kế của chính phủ Úc). Các nhóm và nhà phát triển quan tâm đến khả năng truy cập và làm việc với React có thể xem qua các dự án như thế này và sử dụng các thành phần và phương pháp hay nhất được cung cấp.

Các nhóm và nhà phát triển quan tâm đến khả năng truy cập nhưng sử dụng Vue.js, Angular, Svelte, v.v. có thể xem xét mã React và học hỏi từ đó. Mặc dù có thể có sự khác biệt tự nhiên trong cú pháp của từng khung, nhưng chúng có nhiều khái niệm cơ bản chung. Các thư viện React khác được coi là có thể truy cập và có sẵn làm cơ sở để học:
Để cải thiện khả năng truy cập của Vue.js, bạn cũng nên theo dõi những người có khả năng truy cập từ thế giới React:
  • Marcy Sutton là một chuyên gia về khả năng truy cập web tự do, từng làm việc cho Deque và cải thiện khả năng truy cập cùng các tài liệu liên quan tại Gatsby.js, một trình tạo trang web tĩnh dựa trên React. Cô ấy rất thực tế, tiến hành nghiên cứu và truyền đạt các chủ đề quan trọng liên quan đến khả năng truy cập ứng dụng web trong các bài thuyết trình, bài đăng trên blog và hội thảo tuyệt vời. Bạn có thể tìm thấy Marcy Sutton trên Twitter tại @marcysutton, các khóa học liên quan đến ứng dụng web trên Egghead.ioTestingAccessibility.com hoặc tổng quan về tất cả các dự án của cô ấy bằng cách truy cập trang web của cô ấy.
  • Lindsey Kopacz là một nhà phát triển web chuyên về khả năng truy cập. Cô ấy quan tâm đến các trải nghiệm toàn diện trên web, về việc vượt qua chủ nghĩa phân biệt đối xử với người khuyết tật và giáo dục các nhà phát triển web đồng nghiệp của mình về tầm quan trọng của khả năng truy cập. Ngoài việc viết trên blog a11ywithlindsey.com, cô còn có các khóa học trên Egghead.io và gần đây đã xuất bản sách điện tử “The Bootcampers Guide to Web Accessibility”. Trên Twitter, cô là @littlekope.
  • Ryan Florence và Michael Jackson đã tạo ra Reach UI, một bộ sưu tập các thành phần và công cụ nhằm mục đích “trở thành nền tảng dễ tiếp cận của hệ thống thiết kế dựa trên React của bạn”. Bên cạnh thực tế là họ đã tạo ra một số thành phần tiêu chuẩn có thể truy cập được, điều đặc biệt đáng chú ý là "Reach UI Router" của họ (cùng với các tính năng trợ năng của nó) sẽ hợp nhất với React Router "chính thức" trong tương lai.

    Mặc dù React không tạo ra "các plugin hạng nhất" như Vue.js, nhưng đây là một tin tuyệt vời vì họ đã tạo ra bộ định tuyến của mình với tính năng quản lý tiêu điểm tích hợp. Một tính năng và cải tiến về khả năng truy cập sẽ sớm mang lại lợi ích cho mọi người sử dụng React Router và người dùng của họ.

Insight 3: $refs của Vue rất tuyệt vời để quản lý tiêu điểm​

Quản lý tiêu điểm?​

Bạn đã gặp phải một cách để gửi thông báo có thể truy cập được bằng cách sử dụng ARIA Live Regions trong Insight trước. Một cách khác để giải quyết các vấn đề mà một tài liệu có tính động cao gây ra cho người dùng trình đọc màn hình và bàn phím là quản lý tiêu điểm theo chương trình. Trước khi tôi bắt đầu giải thích thêm về quản lý tiêu điểm, xin lưu ý: Thông thường, việc thay đổi tiêu điểm thông qua tập lệnh là không tốt và bạn nên tránh làm như vậy.

Người dùng không muốn tiêu điểm của họ bị làm phiền. Nếu tiêu điểm thay đổi và hoàn toàn bất ngờ, thì sự can thiệp như vậy sẽ gây phiền toái hoặc thậm chí trở thành rào cản thực sự. Mặt khác, đôi khi thay đổi tiêu điểm theo chương trình là tùy chọn hợp lý duy nhất trong các tiện ích hoặc ứng dụng dựa trên JavaScript để giúp người dùng dựa vào việc sử dụng bàn phím. Tuy nhiên, trong trường hợp này, việc thay đổi tiêu điểm phải có thể dự đoán được. Một cách tốt để đảm bảo khả năng dự đoán này là đảm bảo rằng sự thay đổi tiêu điểm chỉ xảy ra sau một tương tác, chẳng hạn như nhấp vào nút hoặc liên kết.

Những trường hợp nào mà quản lý tiêu điểm có thể cải thiện khả năng truy cập của ứng dụng?
  1. Cần quản lý tiêu điểm khi nội dung bị ảnh hưởng bởi một tương tác (ví dụ: ) không theo trình kích hoạt (ví dụ: ) trực tiếp trong tài liệu. Ví dụ: khái niệm tiện ích tiết lộ giả định rằng vùng chứa mà nút chuyển đổi nằm ngay bên dưới nút trong cây DOM.

    Cấu trúc tài liệu này, khoảng cách gần của trình kích hoạt và vùng chứa phản ứng này không thể được đảm bảo trong mọi tiện ích, do đó, tiêu điểm phải được quản lý chủ động. Khi hộp thoại modal mở ra sau khi kích hoạt nút, không thể đảm bảo rằng các nút HTML của nó theo trực tiếp nút kích hoạt trong DOM. Do đó, tiêu điểm đã được gửi chủ động vào modal, đảm bảo rằng người dùng chỉ sử dụng bàn phím và trình đọc màn hình có thể sử dụng tiện ích cụ thể.
  2. Khi các phần của tài liệu đã thay đổi mà không tải lại trang hoặc các phần của DOM đã được cập nhật (một lần nữa, sau khi tương tác như nhấp vào nút), thì việc gửi tiêu điểm đến nội dung đã thêm hoặc đã thay đổi là phù hợp.

    Một ví dụ về điều này là điều hướng giữa các tuyến đường ("trang") trong Ứng dụng trang đơn: Vì chúng không tải lại tài liệu HTML (như các trang web tĩnh), nên người dùng chỉ sử dụng bàn phím hoặc trình đọc màn hình không được đưa đến đầu "trang mới". Bởi vì những gì đang xảy ra không phải là tải trang "thích hợp" — mà là sửa đổi một phần nhất định của cùng một trang.
Bạn có thể xem các ví dụ về cách quản lý tiêu điểm tốt và xấu trong các bản demo sau đây do Manuel Matuzović cung cấp. Mặc dù khuôn khổ cơ bản (React) và mẫu UI cơ bản (hộp thoại modal) khác nhau, nhưng vấn đề vẫn như vậy:

Một ví dụ về thiếu quản lý tiêu điểm:
Tiêu điểm bàn phím vẫn nằm trong các phần không hoạt động của UI, "phía sau" hộp thoại đã mở
Một ví dụ về quản lý tiêu điểm tốt:
Điểm nhấn được gửi vào hộp thoại modal khi mở
Điều đó khiến các nhà phát triển có trách nhiệm phải gửi điểm nhấn bàn phím đến các phần tử cụ thể cho mẫu của bạn. May mắn thay, các khuôn khổ JavaScript có khái niệm về tham chiếu nút DOM hoặc "ref". Trong Vue.js, chỉ cần thêm thuộc tính ref vào một nút HTML. Sau đó, tham chiếu đến nút này có sẵn trong đối tượng $this.refs. Cuối cùng, việc tập trung vào một phần tử theo chương trình cũng dễ dàng như gọi phương thức .focus() gốc của JavaScript trên phần tử đó.

Đối với ví dụ tiếp theo, hãy giả sử chúng ta có một nút ở đâu đó trong thành phần của mình và áp dụng ref có tên triggerButton cho nút đó. Chúng ta muốn đặt điểm nhấn vào nút đó sau khi người dùng nhấn phím ESC. Mã của chúng tôi cho việc này sẽ trông như sau:
Mã:
  Trigger export default {//...methods: { focusTriggerBtn() { this.$refs.triggerButton.focus(); }}//...}

Điều hướng Off-Canvas của Modal​

Một cách sử dụng khác của cả quản lý tham chiếu và tiêu điểm là triển khai có thể truy cập được của điều hướng Off-Canvas.



Trong trường hợp này, bạn cần thiết lập ít nhất hai tham chiếu: Một cho nút kích hoạt mở điều hướng (gọi là navTrigger) và một cho phần tử được lấy nét ngay khi điều hướng hiển thị (navContainer trong ví dụ này, là phần tử cần tabindex="-1" có thể lấy nét theo chương trình). Vì vậy, khi nhấp vào nút kích hoạt, tiêu điểm sẽ được đưa vào chính phần điều hướng. Và ngược lại: Ngay khi điều hướng đóng lại, tiêu điểm phải quay trở lại trình kích hoạt.

Sau khi đọc các đoạn văn trên, tôi hy vọng một điều trở nên rõ ràng với bạn, độc giả thân mến: Khi bạn hiểu được tầm quan trọng của việc quản lý tiêu điểm, bạn nhận ra rằng tất cả các công cụ cần thiết đều nằm trong tầm tay bạn — cụ thể là this.$refs của Vue và .focus()

Kết luận​

Bằng cách nêu bật một số phát hiện cốt lõi của tôi liên quan đến khả năng truy cập ứng dụng web, tôi hy vọng rằng tôi đã có thể giúp giảm bớt bất kỳ nỗi sợ hãi lan tỏa nào về chủ đề này có thể đã tồn tại và bây giờ bạn cảm thấy tự tin hơn khi xây dựng các ứng dụng có thể truy cập được với sự trợ giúp của Vue.js (nếu bạn muốn tìm hiểu sâu hơn về chủ đề này, hãy xem liệu cuốn sách điện tử nhỏ “Accessible Vue” của tôi có thể giúp bạn trong suốt hành trình này không).

Ngày càng có nhiều trang web trở nên giống ứng dụng hơn và sẽ thật đáng buồn nếu những sản phẩm kỹ thuật số tuyệt vời này vẫn còn nhiều rào cản như vậy chỉ vì các nhà phát triển web không biết chính xác nên bắt đầu chủ đề từ đâu. Đó là khoảnh khắc thực sự cho phép khi bạn nhận ra rằng phần lớn khả năng truy cập ứng dụng web thực sự là khả năng truy cập web "cũ kỹ" và đối với phần còn lại, đường dành cho bò đã được trải nhựa.
 
Back
Bên trên