Haskell Yesod首页路由Hamlet模板<head>/<title>标签解析异常求助
问题根源分析
你遇到的问题是Yesod框架的defaultLayout已经自动帮你生成了完整的HTML外层结构,包括<html>、<head>(默认带空<title>)和<body>标签。而你在whamlet模板里手动添加了<head>标签,这个标签会被当作页面内容的一部分,被嵌套到defaultLayout生成的<body>内部,最终就出现了浏览器看到的异常结构:第一个<head>是框架生成的空内容版本,第二个你自定义的<head>却跑到了<body>里。
解决方案
Yesod提供了专门的API来处理页面标题和元标签,完全不需要手动写<head>标签。你需要把原来模板里的<head>部分移到defaultLayout的do块中,用框架提供的函数来配置:
修改后的代码
getHomeR :: Handler Html getHomeR = do clearSession key <- liftIO $ MYP.randomString 9 setSession "cache_key" (T.pack key) sess <- getSession -- Generate the location form (widget, enctype) <- generateFormPost $ renderDivs locationForm defaultLayout $ do -- 设置页面标题,自动插入到框架生成的<head>中 setTitle "Fishing Weather Hub" -- 添加元标签,指定插入到<head>区域 toWidgetHead [hamlet| <meta name="description" content="Completely free fishing weather data provided by NOAA and Open Weather Maps. Designed to be simple and easy to use."> <meta name="keywords" content="fishing weather,fishing,weather"> <meta name="robots" content="index,follow"> |] -- 页面主体内容(无需手动写<head>或<body>) [whamlet| <header> <center style="font-size:30px">Fishing Weather Hub <br> <form method=post action=@{ProcessLocationFormR} enctype=#{enctype}> ^{widget} <button>Submit <a href="https://www.anglerwise.com/2010/02/09/how-does-barometric-pressure-affect-fishing/">How does barometric pressure affect fishing? |] --CSS toWidget [lucius| form { margin: 0 auto; width:250px; } |]
关键说明
setTitle:Yesod专门用来设置页面标题的函数,它会自动把标题填充到框架生成的<head>内的<title>标签中。toWidgetHead:用来将指定内容插入到页面的<head>区域,非常适合添加元标签、额外样式或脚本。- 页面的主体内容(
<header>、表单等)直接写在whamlet模板里即可,它们会被自动嵌套到defaultLayout生成的<body>内部,完全不需要手动编写<body>标签。
这样修改后,生成的HTML结构就会完全符合预期:一个包含正确<title>和所有元标签的<head>,以及仅包含页面主体内容的<body>。
内容的提问来源于stack exchange,提问作者Nicholas Hubbard
相关产品推荐
相关产品推荐

