首次搭建Middleman站点:如何生成单个人物静态详情页
嘿,我来帮你搞定这个问题!要实现访问/people/bob.html只显示Bob的信息,核心是利用Middleman的**动态页面生成(Dynamic Pages)**功能,分三步就能解决:
第一步:给每个人物加唯一URL标识(可选但推荐)
首先,你需要给data/people.yml里的每一位朋友添加一个slug字段——这是用来生成友好URL的唯一标识,避免名字里的空格或特殊字符导致URL问题。如果不想手动加,后面也可以自动生成,先看手动配置的例子:
friends: - name: Bob Smith address: 101 Foo Lane birth: 1966-03-03 slug: bob # 对应URL /people/bob.html - name: Mary Johnson address: 120 Bar St birth: 1967-06-18 slug: mary # 对应URL /people/mary.html
如果担心手动加slug麻烦,也可以让Middleman自动从名字生成(比如把Bob Smith转成bob-smith),后面会说怎么实现。
第二步:在config.rb里配置页面生成规则
打开项目根目录的config.rb,添加以下代码,告诉Middleman要为每个人物生成单独的页面:
# 遍历所有朋友数据,批量生成单页 data.people.friends.each do |friend| # 第一个参数:最终生成的页面URL路径 # 第二个参数:用来渲染页面的模板文件路径 # locals:把当前人物的数据传给模板 # ignore: true:告诉Middleman不要把模板本身当成独立页面输出 proxy "/people/#{friend.slug}.html", "/people/show.html", locals: { current_friend: friend }, ignore: true end
自动生成slug的优化版
如果不想手动加slug字段,可以用参数化方法自动从名字生成,修改上面的代码:
# 自动把名字转成URL友好的slug(比如Bob Smith → bob-smith) data.people.friends.each do |friend| slug = friend.name.downcase.gsub(' ', '-') # 简单的手动转换 # 或者用更专业的参数化方法(Middleman默认集成了ActiveSupport的话可以用) # slug = friend.name.parameterize proxy "/people/#{slug}.html", "/people/show.html", locals: { current_friend: friend }, ignore: true end
第三步:创建单页模板文件
在source/people目录下新建一个模板文件show.html.erb,这个文件会用来渲染每一个人物的页面内容,代码很简单:
<h1><%= current_friend.name %></h1> <div class="person-info"> <p><strong>地址:</strong> <%= current_friend.address %></p> <p><strong>生日:</strong> <%= current_friend.birth %></p> </div>
这里的current_friend就是我们在config.rb里通过locals传过来的当前人物数据,直接调用对应的字段就能展示信息了。
为什么你之前的尝试失败了?
你之前写的<% data.people.friends.each do |name, person| %>有个小问题:friends是一个数组,数组的each方法每次遍历得到的是单个的人物哈希(比如{name: "Bob Smith", ...}),而不是键值对|name, person|——那种写法是用来遍历哈希的,所以自然取不到正确的数据~
针对20000个页面的小提示
因为你要生成大量页面,注意两个优化点:
- 测试阶段先用少量数据调试,没问题再全量生成;
- 可以在
config.rb里加一些性能优化配置,比如关闭不必要的扩展、压缩输出的HTML:set :build_dir, 'build' # 如果用ERB模板,开启压缩 set :erb, { trim_mode: '-' } # 关闭不需要的Middleman扩展,加快构建速度 activate :minify_html
现在运行middleman build,就能在build/people目录下看到所有生成的单页啦!
内容的提问来源于stack exchange,提问作者Pilot

