html标签转化成vnode插件,类vue将template转为vnode的流程

本文介绍了一个HTML解析器的核心实现过程,包括起始标签、文本内容及闭合标签的处理方式。解析器通过核心函数逐步推进索引,识别并处理标签与属性,最终形成规范化的元素结构。

核心函数parseStartTag(起始标签处理函数,得到tagName,匹配attrs得到key,value)执行完毕后调用parseHTML函数中填写的options.start,设置根元素,父级元素,并储存当前element于stack数组中,方便结束标签函数执行时的取出处理

核心函数parseText(文本处理函数,得到{{}}之中的内容msg)判断条件是未能匹配

核心函数parseEndTag(结束标签处理函数)判断最后一个元素是否与当前的闭合标签tagname匹配,匹配的话执行options.end将之前stack数组中储存的上一个标签移动到前一个标签的子类并在stack数组中删除他

核心函数advance,推进索引,将已经匹配过的标签或属性从模板中剔除

全文主要以parse执行parseHTML,parse传入两个参数,template模板,options(start:判断起始标签,将得到的elemnt格式化为标准模式,end:判断结束标签,将父级向上一层滚动,chars将{{}}内容截取)

起始标签的匹配细节

1.判断是否以

advance将index向前推进

若此时匹配不到起始标签的闭合符号“>”,且能够匹配到属性如id=“abc”,那么将index继续向前推id=“abc”的长度,删除模板中id属性,循环操作直到匹配得到起始标签的闭合符号,index再推进>符号的长度,模板删除>后,记录此时为起始标签的结束位置

此时我们匹配得到的元素还不够规范,长这样⏬,需要进行修改

{tagName: "div", attrs: 0: [" id="abc"", "id", "=", "abc", undefined, undefined, index: 0, input: " id="abc">

{{msg}}

{{msg1}}

", groups: undefined], start: 0, end: 14}

handleStartTag方法判断是否为单标签,若不是即将格式化后的对象塞入数组stack中这里面没有start,end.只有{id:"abc"}和标签名,将lastTag设置为当前格式化完毕的标签

attrsMap:{id: "abc"}

children:[]

parent:undefined

tag:"div"

type:1

最后进行parse的options.start处理,将第一个标签设置为CurrentParent,同时设为根元素,这样第一个标签

就处理完毕

子元素标签的匹配

由于模板还没遍历完毕,继续执行parseHTML,此时模板

html = "

{{msg}}

{{msg1}}

"

匹配到p的起始标签继续执行新的一轮起始标签的匹配,区别在于此时需要设置currentParent即上一次遍历得到的div标签处理后的element的children数组属性加入当前p标签处理后的element,再将currentParent赋值为当前element,并且stack中塞入element,方便以后取出

文本匹配

此时模板为如下,不再匹配

html = "{{msg}}

{{msg1}}

"

设置var text = (void 0), rest = (void 0), next = (void 0);除了防止被重写外,还可以减少字节。void 0代替undefined省3个字节。

html.substring(0, >标签所在位置)截取得到{{msg}}, html.slice(>标签所在位置)截取得到剩余的模板,将索引向前推进{{msg}}长度,获取剩余模板

此后执行parse的options.chars方法处理text,parseText处理文本塞入tokens数组中得到tokens = ["_s(msg)"],currentParent的children加入type为2标记为文本标签

{type: 2, expression: "_s(msg)+_s(msg)", text: "{{msg}}"}

闭合标签匹配

匹配完毕将index推进

个长度,获取剩余模板,执行parseEndTag

parseEndTag通过stack找到最近一个元素的标签,如果存在执行options.end方法处理,将stack最后一个元素进行pre元素处理TODO:

处理完该闭合标签后将stack长度减一并把currentParent指向最后一位,即闭合标签的父级,因为此时最高级div标签的elemnet的children已经完成了p标签的导入

{attrs:[{…}]

attrsList:[{…}]

attrsMap:{id: "abc"}

children:Array(1)0:{type: 1, tag: "p", attrsList: Array(1), attrsMap: {…}, parent: {…}, …}

parent:undefined

tag:"div"

type:1}

Vue.js 中将组件或代码换为纯 HTML 代码,可以通过多种方式实现。以下是几种常见方法及其适用场景。 ### 使用 `v-html` 指令渲染 HTML 字符串 如果目标是将一个包含 HTML 标签的字符串直接渲染到 DOM 元素中,可以使用 Vue 的内置指令 `v-html`。这个指令会将数据作为原始 HTML 插入到元素中,而不是将其作为纯文本显示[^1]。 ```html <template> <div v-html="rawHtml"></div> </template> <script> export default { data() { return { rawHtml: '<p style="color: red;">这是一个红色段落。</p>' }; } }; </script> ``` 需要注意的是,`v-html` 可能存在安全风险,因为它会绕过 Vue 的数据绑定机制并直接操作 DOM。因此,在处理用户提供的内容时应格外小心,以防止 XSS 攻击。 ### 提取富文本中的纯文本 如果目标是从 Vue 组件中获取 HTML 内容,并从中提取纯文本,可以使用正则表达式来去除所有 HTML 标签和属性。这种方法适用于需要将富文本内容(如从编辑器中获取的内容)换为无格式文本的情况[^2]。 ```javascript function stripHtmlTags(html) { return html.replace(/<[^>]+>/g, ''); } const htmlContent = '<p>这是<strong>一段加粗文字</strong></p>'; const plainText = stripHtmlTags(htmlContent); console.log(plainText); // 输出:这是一段加粗文字 ``` ### 单文件组件与构建工具 对于单文件 `.vue` 组件,通常不会手动将其换为 HTML 文件,而是通过构建工具(如 Webpack 或 Vite)配合 `vue-loader` 等插件自动处理这些组件,最终生成静态 HTML、CSS 和 JavaScript 资源[^3]。这种方式适合于生产环境部署。 ### 渲染虚拟节点 (VNode) 并换为 HTML 字符串 在某些特殊情况下,可能需要将 Vue 组件实例渲染为虚拟节点 (VNode),然后将其换为 HTML 字符串。这种需求通常出现在服务端渲染 (SSR) 或动态生成 HTML 内容的场景中。Vue 官方提供了 `renderToString` 方法来完成这一任务,但该功能主要依赖于 Node.js 环境下的 `vue-server-renderer` 包。 ```javascript import { createRenderer } from 'vue-server-renderer'; const renderer = createRenderer(); const app = { template: `<div>Hello, {{ name }}</div>`, data() { return { name: 'Vue' }; } }; renderer.renderToString(app, (err, html) => { if (err) throw err; console.log(html); // 输出:<div data-server-rendered="true">Hello, Vue</div> }); ``` ### 总结 - **`v-html`** 用于直接插入 HTML 字符串。 - **正则替换** 可用于提取纯文本。 - **构建工具** 处理 `.vue` 文件生成最终 HTML。 - **服务端渲染** 可以将 Vue 实例换为 HTML 字符串。 每种方法都有其特定的应用场景,选择合适的方式取决于具体的需求和技术栈配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值