首页引入Twitter Cards时出现ReferenceError,求DRY原则解决方案
解决EJS头部组件中Twitter卡片变量未定义的DRY方案
你的问题很典型——复用组件时遇到了上下文变量缺失的问题,完全不用放弃DRY原则,这里有几个优雅的解决方案:
方案1:在头部组件中添加条件判断(最简单快捷)
直接修改header.ejs,给Twitter卡片的动态内容加上存在性检查,当blog变量不存在时(比如在index列表页),使用站点默认的标题和图片:
<head> ... <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:site" content="@DrDenverHBubble"> <meta name="twitter:creator" content="@DrDenverHBubble"> <!-- 检查blog是否存在,不存在则用默认值 --> <meta name="twitter:title" content="<%= typeof blog !== 'undefined' ? blog.title : 'Dr Denver\'s Blog - All Posts' %>"></meta> <meta name="twitter:image" content="<%= typeof blog !== 'undefined' ? blog.image : '/assets/default-home-banner.jpg' %>"></meta> </head>
这样修改后,index页面渲染header时会自动用默认值,show页面则使用当前blog的内容,完全不用拆分或重复代码。
方案2:统一传递meta配置对象(更清晰易维护)
如果以后需要添加更多meta标签(比如Open Graph),这种方法扩展性更好:
在路由中传递统一的meta数据:
- 列表页(index)路由:
app.get('/blogs', (req, res) => { Blog.find({}, (err, blogs) => { if (err) { // 错误处理逻辑 } else { res.render('blogs/index', { blogs: blogs, noMatch: req.query.noMatch || null, // 传递首页的meta配置 meta: { title: 'Dr Denver\'s Blog - All Posts', image: '/assets/default-home-banner.jpg' } }); } }); }); - 详情页(show)路由:
app.get('/blogs/:id', (req, res) => { Blog.findById(req.params.id, (err, foundBlog) => { if (err) { // 错误处理逻辑 } else { res.render('blogs/show', { blog: foundBlog, // 传递当前文章的meta配置 meta: { title: foundBlog.title, image: foundBlog.image } }); } }); });
- 列表页(index)路由:
修改header.ejs使用统一的meta变量:
<head> ... <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:site" content="@DrDenverHBubble"> <meta name="twitter:creator" content="@DrDenverHBubble"> <meta name="twitter:title" content="<%= meta.title %>"></meta> <meta name="twitter:image" content="<%= meta.image %>"></meta> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> ... </head>
这种方式把动态meta数据从业务变量(blog)中抽离出来,逻辑更清晰,后续扩展其他meta标签也更方便。
方案3:拆分组件(适合复杂项目)
如果你的头部还有很多其他动态内容,可以把通用头部和动态meta标签拆成两个组件:
通用header组件(header.ejs):
<head> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <!-- 其他通用样式、脚本、meta标签 --> <% include ./meta-tags %> </head>动态meta标签组件(meta-tags.ejs):
<meta name="twitter:card" content="summary_large_image"> <meta name="twitter:site" content="@DrDenverHBubble"> <meta name="twitter:creator" content="@DrDenverHBubble"> <meta name="twitter:title" content="<%= meta.title %>"></meta> <meta name="twitter:image" content="<%= meta.image %>"></meta>
然后在路由中传递meta变量的方式和方案2一致,这种拆分让组件职责更单一,适合头部内容较多的项目。
这三种方案都能帮你遵循DRY原则,不用重复编写头部代码,同时解决变量未定义的错误,你可以根据自己项目的复杂度选择最合适的方式~
内容的提问来源于stack exchange,提问作者JS Bach
相关产品推荐
相关产品推荐

