解析 URL
在实际的网络应用中,我们希望针对不同的 URL 显示不同的内容
/search
/search?q=seiza
/settings
我们如何实现?我们使用 elm/url
将原始字符串解析为漂亮的 Elm 数据结构。当您只看示例时,就能理解该软件包的点睛之处,因此我们就是这么做的!
示例 1
假设我们有一个艺术网站,其中以下地址应有效
/topic/architecture
/topic/painting
/topic/sculpture
/blog/42
/blog/123
/blog/451
/user/tom
/user/sue
/user/sue/comment/11
/user/sue/comment/51
因此,我们可以使用 Url.Parser
模块,针对这些内容编写 URL 解析器如下所示
import Url.Parser exposing (Parser, (</>), int, map, oneOf, s, string)
type Route
= Topic String
| Blog Int
| User String
| Comment String Int
routeParser : Parser (Route -> a) a
routeParser =
oneOf
[ map Topic (s "topic" </> string)
, map Blog (s "blog" </> int)
, map User (s "user" </> string)
, map Comment (s "user" </> string </> s "comment" </> int)
]
-- /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/bob/comment/42 ==> Just (Comment "bob" 42)
-- /user/sam/comment/35 ==> Just (Comment "sam" 35)
-- /user/sam/comment/ ==> Nothing
-- /user/ ==> Nothing
Url.Parser
模块使其十分简洁,可以将有效 URL 完整地转换为漂亮的 Elm 数据!
示例 2
现在,假设我们有一个个人博客,其中以下地址有效
/blog/12/the-history-of-chairs
/blog/13/the-endless-september
/blog/14/whale-facts
/blog/
/blog?q=whales
/blog?q=seiza
在这种情况下,我们有单独的博客文章和一个博客概览,其中包含一个可选查询参数。我们需要添加 Url.Parser.Query
模块,以编写这次的 URL 解析器
import Url.Parser exposing (Parser, (</>), (<?>), int, map, oneOf, s, string)
import Url.Parser.Query as Query
type Route
= BlogPost Int String
| BlogQuery (Maybe String)
routeParser : Parser (Route -> a) a
routeParser =
oneOf
[ map BlogPost (s "blog" </> int </> string)
, map BlogQuery (s "blog" <?> Query.string "q")
]
-- /blog/14/whale-facts ==> Just (BlogPost 14 "whale-facts")
-- /blog/14 ==> Nothing
-- /blog/whale-facts ==> Nothing
-- /blog/ ==> Just (BlogQuery Nothing)
-- /blog ==> Just (BlogQuery Nothing)
-- /blog?q=chabudai ==> Just (BlogQuery (Just "chabudai"))
-- /blog/?q=whales ==> Just (BlogQuery (Just "whales"))
-- /blog/?query=whales ==> Just (BlogQuery Nothing)
</>
和 <?>
运算符让我们得以编写一些解析器,其颇似我们要解析的实际 URL。添加 Url.Parser.Query
让我们得以处理诸如 ?q=seiza
之类的查询参数。
示例 3
好的,现在我们有一个文档网站,其中地址如下所示
/Basics
/Maybe
/List
/List#map
/List#filter
/List#foldl
我们可以使用 Url.Parser
中的 fragment
解析器,以便如下处理这些地址
type alias Docs =
(String, Maybe String)
docsParser : Parser (Docs -> a) a
docsParser =
map Tuple.pair (string </> fragment identity)
-- /Basics ==> Just ("Basics", Nothing)
-- /Maybe ==> Just ("Maybe", Nothing)
-- /List ==> Just ("List", Nothing)
-- /List#map ==> Just ("List", Just "map")
-- /List# ==> Just ("List", Just "")
-- /List/map ==> Nothing
-- / ==> Nothing
因此,现在我们也可以处理 URL 片段!
综合
既然我们看到了一些解析器,我们应该看看它们如何适应 Browser.application
程序。与其像上次那样只保存当前 URL,我们能否将其解析为有用的数据并显示出来?
TODO
主要的更新内容如下
- 在收到
UrlChanged
消息时,我们的update
解析 URL。 - 我们的
view
函数针对不同的地址显示不同的内容!
这真的没有什么花哨的。不错!
但是,当你拥有 10、20 或 100 个不同的页面时,会发生什么?它们是否都出现在这个 view
函数中?肯定不能都放在一个文件中。它应该放在多少个文件中?应该是什么目录结构?下面我们将讨论这些内容!