尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

nuxt-markdown-blog-starter如何把Markdown变成Vue渲染函数:frontmatter-markdown-loader双模式与eval原理深度剖析

nuxt-markdown-blog-starter如何把Markdown变成Vue渲染函数:frontmatter-markdown-loader双模式与eval原理深度剖析 nuxt-markdown-blog-starter如何把Markdown变成Vue渲染函数frontmatter-markdown-loader双模式与eval原理深度剖析【免费下载链接】nuxt-markdown-blog-starterNuxt Markdown blog starter项目地址: https://gitcode.com/gh_mirrors/nu/nuxt-markdown-blog-starternuxt-markdown-blog-starter 是一个用 Nuxt Vue 构建的 Markdown 博客模板核心能力是把contents/目录下的.md文件编译成 Vue 渲染函数。本文带你弄清 frontmatter-markdown-loader 的两种工作模式以及页面为什么用eval在运行时复活渲染函数——不需要背代码读懂原理即可。一张图看懂.md 文件是如何变成博客页面的整套链路由四个文件接力完成阶段负责文件做了什么① 构建期nuxt.config.jsWebpack 规则拦截所有.md文件交给 loader 处理② 加载期pages/blog/_slug.vueasyncData按 URL 动态 import 对应.md取出 frontmatter 和渲染函数③ 运行期components/Markdown/DynamicMarkdown.vue用eval把字符串还原成真正的渲染函数并执行④ 展示期浏览器Vue 执行渲染函数Markdown 内容出现在页面上一个典型的 Markdown 长这样——头部是 frontmatter 元数据正文是普通 Markdown--- name: bacon-ipsum title: Bacon Ipsum year: 28 May 2019 id: bacon-ipsum description: | Bacon ipsum dolor amet spare ribs... --- Bacon ipsum dolor amet spare ribs ham t-bone...示例取自 contents/en/blog/bacon-ipsum.md双模式配置frontmatter-markdown-loader 的两种工作模式在 nuxt.config.js 的build.extend中项目注册了一条 Webpack 规则test: /\.md$/loader 为frontmatter-markdown-loader关键是这两个选项options: { mode: [Mode.VUE_RENDER_FUNCTIONS, Mode.VUE_COMPONENT], vue: { root: dynamicMarkdown }, markdown(body) { return md.render(body) } }模式一VUE_RENDER_FUNCTIONS——把模板编译成渲染函数字符串这个模式借鉴了 Vue 官方模板编译器的思路把 Vue 的template编译产物一个 render 函数的代码字符串放进模块导出对象里。loader 处理完.md文件后import 它得到的模块大致有三个属性attributesfrontmatter 里的全部字段title、year、description…vue.render模板编译出的渲染函数代码是字符串vue.staticRenderFns静态片段渲染函数数组同样是字符串页面组件 pages/blog/_slug.vue 正是取走这两段字符串renderFunc: (${fileContent.vue.render}), staticRenderFuncs: [${fileContent.vue.staticRenderFns}],为什么用字符串而不是函数直接传因为 Nuxt 的asyncData返回结果会被序列化、传给客户端 hydration。字符串可以安全穿越服务端 → 客户端这一程函数对象不行。模式二VUE_COMPONENT——在 Markdown 里直接写 Vue 组件这是这个项目最炫的玩法在.md正文中直接写 Vue 标签loader 会把它识别为组件并保留。比如骨架屏教程 contents/en/blog/design-and-code-skeletons-screens.md 里就嵌入了一个可交互的数据表格组件Component :isextraComponentLoader /读者打开文章时看到的不是图片而是能实时操作的 Vue 组件。配合 frontmatter 中的extraComponent字段如extraComponent: Datatablepages/blog/_slug.vue 会动态 import 对应的 components/blog/ 目录下的组件。vue: { root: dynamicMarkdown }则指定了编译产物的根节点命名空间避免与页面自身模板冲突。此外markdown(body)回调把正文交给 markdown-it叠加 markdown-it-prism 语法高亮渲染成 HTML——这就是为什么文章里的代码块有漂亮的材质风格配色样式见 assets/css/prism-material-light.css。eval 原理为什么要在运行时复活渲染函数字符串传到了浏览器最后一步在 components/Markdown/DynamicMarkdown.vuecreated () { this.templateRender eval(this.renderFunc) this.$options.staticRenderFns eval(this.staticRenderFuncs) }eval的作用是把函数代码字符串重新解析为可执行的函数对象。类比一下loader 在构建期把菜谱函数源码打印成了文字版eval就是在厨房里把文字重新读成可执行的指令。几个要点帮助理解为什么构建期不直接合并因为读哪篇文章由 URL 参数slug决定是运行时才知道的事构建期无法预生成所有页面模板为什么放在client-only中pages/blog/_slug.vue 用client-only包裹该组件让eval只在浏览器执行跳过 SSR 阶段安全边界这里eval的输入只来自项目仓库内的 Markdown 文件不掺任何用户输入属于可控场景——这也是为什么它只适合内容在自己仓库里的 Markdown 博客不适合开放投稿场景新手上手三步跑通 Markdown 博客第 1 步获取项目git clone https://gitcode.com/gh_mirrors/nu/nuxt-markdown-blog-starter cd nuxt-markdown-blog-starter npm install npm run dev浏览器打开http://localhost:3000即可预览。第 2 步写你的第一篇文章在 contents/en/blog/ 下新建my-first-post.md按 frontmatter 正文的格式编写参考 contents/en/blog/vuex-what-is-when-use-it.md再在 contents/en/blogsEn.js 中登记文件名首页列表和静态路由generate.routes见 nuxt.config.js会自动包含它。第 3 步在正文里嵌入组件可选frontmatter 中加extraComponent: 组件名并在contents/对应语言目录下写.vue文件——文章里就能出现交互组件了原理即上文的 VUE_COMPONENT 模式。小结这套方案的价值与适用边界纯 Markdown 写作内容即文件无需数据库和后台天然适配 Git 版本管理双模式各管一段VUE_RENDER_FUNCTIONS 负责正文高效渲染VUE_COMPONENT 负责正文可交互eval 是桥梁用运行时字符串求值弥补了构建期产物与运行时按需加载之间的裂缝适用边界内容源必须可信在自己仓库内开放投稿场景应改用纯 HTML 渲染方案理解了这条loader → 字符串传输 → eval 复活的链路你就掌握了 nuxt-markdown-blog-starter 从 Markdown 到 Vue 渲染函数最核心的一环 【免费下载链接】nuxt-markdown-blog-starterNuxt Markdown blog starter项目地址: https://gitcode.com/gh_mirrors/nu/nuxt-markdown-blog-starter创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表