[Declarative Programming + Elm] Bài 16 – URL Parser Module

Để xây dựng một Web App thực sự thì hiển nhiên là chúng ta sẽ muốn hiển thị những nội dung khác nhau tương ứng với các Url khác nhau, không chỉ đối với những liên kết tĩnh như trang chủ / hay trang giới thiệu /about mà còn những liên kết có chứa các

Để xây dựng một Web App thực sự thì hiển nhiên là chúng ta sẽ muốn hiển thị những nội dung khác nhau tương ứng với các Url khác nhau, không chỉ đối với những liên kết tĩnh như trang chủ / hay trang giới thiệu /about mà còn những liên kết có chứa các tham số truy vấn ví dụ như /search?q=seiza.

Để tạo ra logic điều hướng dựa trên các liên kết có chứa tham số truy vấn như vậy thì chúng ta cần học cách sử dụng thêm một số công cụ được cung cấp bởi package elm/url mà chúng ta đã cài đặt trước đó. Và ở đây, chúng ta sẽ tiếp tục xem xét ví dụ được Elm đẳng tải trong loạt bài viết hướng dẫn trên trang web chính thức của họ.

Ví dụ 1

Giả sử chúng ta đang có một website và các path được liệt kê dưới đây đều hợp lệ.

  • /topic/architecture
  • /topic/painting
  • /topic/sculpture
  • /blog/42
  • /blog/123
  • /blog/451
  • /user/tom
  • /user/sue
  • /user/sue/comment/11
  • /user/sue/comment/51

Như vậy là chúng ta đang có các trang hạng mục topic, các trang bài viết blog, các trang thông tin người dùng user, và phương thức để tìm kiếm bình luận của người dùng. Và bây giờ chúng ta có code ví dụ sử dụng module Url.Parser để viết một chương trình phân tích đường dẫn Url như sau:

typeRoute=TopicString|BlogInt|UserString|CommentStringIntrouteParser:Parser(Route->a)arouteParser=oneOf[mapTopic(s"topic"</>string),mapBlog(s"blog"</>int),mapUser(s"user"</>string),mapComment(s"user"</>string</>s"comment"</>int)]

Chúng ta đang có hàm routeParser không có tham số đầu vào và sẽ trả về một trình khởi tạo Parser với thông tin định kiểu cụ thể là Parser (Route -> a) a. Tất cả các hàm hỗ trợ s, </>, string, int, đều được import từ module Url.Parser và được thiết kế để có cú pháp sử dụng ở bề mặt code tương ứng với định dạng của path mà chúng ta cần tách lấy các tham số truy vấn.

Ok, như vậy là với cú pháp biểu thị dạng đường dẫn path cần tách lấy các tham số như trên thì chúng ta có:

  • Các chuỗi tĩnh trong path được mô tả bởi các lời gọi hàm s
  • Các lời gọi hàm </> tương ứng với các dấu xổ nghiêng / trong path
  • Và các hàm string, int, mô tả vị trí tách lấy các tham số truy vấn và kiểu dữ liệu trả về

Và đây là kết quả hoạt động của trình Parser được trả về bởi hàm routeParser.

-- /topic/pottery        ==>  Just (Topic "pottery")-- /topic/collage        ==>  Just (Topic "collage")-- /topic/               ==>  Nothing-- /blog/42              ==>  Just (Blog 42)-- /blog/123             ==>  Just (Blog 123)-- /blog/mosaic          ==>  Nothing-- /user/tom/            ==>  Just (User "tom")-- /user/sue/            ==>  Just (User "sue")-- /user/                ==>  Nothing-- /user/bob/comment/42  ==>  Just (Comment "bob" 42)-- /user/sam/comment/35  ==>  Just (Comment "sam" 35)-- /user/sam/comment/    ==>  Nothing

Việc đọc code định nghĩa của các hàm đã sử dụng trong module Url.Parser cũng quan trọng nhưng không hẳn là cần thiết ở thời điểm khởi đầu, bởi chúng ta đã nhìn thấy cú pháp sử dụng ở dạng mô tả trực quan rất declarative, dễ hiểu và dễ áp dụng theo mà không cần phải đọc hiểu trình tự hoạt động cụ thể của các lời gọi hàm ở đây.

Ví dụ 2

Bây giờ là một trường hợp ví dụ khác khi chúng ta đang có một trang blog cá nhân với các đường dẫn hợp lệ như sau:

  • /blog/12/the-history-of-chairs
  • /blog/13/the-endless-september
  • /blog/14/whale-facts
  • /blog/
  • /blog?q=whales
  • /blog?q=seiza

Trong trường hợp này, chúng ta đang có các trang bài viết /blog/number/ và các trang kết quả tìm kiếm /blog?q=... với tham số truy vấn ở khóa q=. Để tách lấy tham số các thám số truy vấn tùy chọn ở vị trí khóa q= thì chúng ta cần sử dụng thêm module Url.Parser.Query.

import Url.Parser exposing(Parser,(</>),(<?>),int,map,oneOf,s,string)import Url.Parser.Query as QuerytypeRoute=BlogPostIntString|BlogQuery(MaybeString)routeParser:Parser(Route->a)arouteParser=oneOf[mapBlogPost(s"blog"</>int</>string),mapBlogQuery(s"blog"<?>Query.string"q")]

Cú pháp áp dụng trong trường hợp này cũng hoàn toàn dễ nhìn thấy dạng của path được mô tả trong code. Và đây là kết quả hoạt động của trình Parser được trả về bởi hàm routeParser.

`/blog/12/the-history-of-chairs`  ==>  Just (BlogPost 12 "the-history-of-chairs")
`/blog/13/the-endless-september`  ==>  Just (BlogPost 13 "the-endless-september")
`/blog/14/whale-facts`            ==>  Just (BlogPost 14 "whale-facts")
`/blog/`                          ==>  Just (BlogQuery Nothing)
`/blog?q=whales`                  ==>  Just (BlogQuery (Just "whales"))
`/blog?q=seiza`                   ==>  Just (BlogQuery (Just "seiza"))

Ví dụ 3

Và ví dụ cuối cùng là chúng ta có một website dạng trang tài liệu tổng hợp với các đường dẫn hợp lệ như sau:

  • /Basics
  • /Maybe
  • /List
  • /List#map
  • /List#filter
  • /List#foldl

Trong trường hợp này, chúng ta đang có các đường dẫn chứa các tên định danh id của một phần tử HTML nào đó. Và để tách lấy các id này thì chúng ta sẽ cần sử dụng thêm hàm fragment trong module Url.Parser.

typealiasDocs=(String,MaybeString)docsParser:Parser(Docs->a)adocsParser=mapTuple.pair(string</>fragmentidentity)

Như vậy là chúng ta có các lời gọi hàm </> fragment identity để bắt đầu tách lấy #id ở đoạn cuối cùng của path, có phần hơi đặc biệt. Tuy nhiên chúng ta cũng có thể đọc theo cách đơn giản, </> fragment là ký hiệu #, và identity là vị trí của chuỗi id cần tách lấy trong path. Và đây là kết quả hoạt động tương ứng.

-- /Basics        ==>  Just ("Basics", Nothing)
-- /Maybe         ==>  Just ("Maybe", Nothing)
-- /List          ==>  Just ("List", Nothing)
-- /List#map      ==>  Just ("List", Just ("map"))
-- /List#filter   ==>  Just ("List", Just ("filter"))
-- /List#foldl    ==>  Just ("List", Just ("foldl"))

Như vậy là chúng ta cũng đã biết thêm cách sử dụng module Url để tách lấy các tham số truy vấn trong path để có thể sử dụng cho logic xử lý trong hàm update của Browse.application.

Sau đó thì update sẽ tạo ra một bản ghi model mới tương ứng với thông tin truy vấn được để view có thể điều chỉnh giao diện hiển thị của trang đơn cho phù hợp với yêu cầu của người dùng. Phần còn lại của câu chuyện lúc này là chúng ta chưa có cách thức để thay đổi nội dung của phần tử <head> bởi Elm không có module nào hỗ trợ.

[Declarative Programming + Elm] Bài 17 – JavaScript Interop

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ