用好Emmet提升前端编码效率的实用技巧
说实话,Emmet我只用这一个方案
先说结论:不管你在用什么前端工具链,只要你还在手写HTML结构,Emmet必须给我用起来。而且别整那些花里胡哨的自定义扩展,就用编辑器自带的那一套——VS Code默认的Emmet,够了。
我知道有人折腾过Emmet插件、自定义语法、甚至搞个构建流程预编译Emmet片段。我也试过,结果呢?折腾半天发现根本没必要。你现在写的代码可能五分钟就能生成出来,但我非得花两小时配个“高效”方案,最后还因为版本更新出bug,谁懂啊。
今天我就来聊聊我踩过的几个坑,对比下几种常见的“Emmet玩法”,说说为啥我现在只认默认那一套。
三种常见的“Emmet用法”
第一种:原生Emmet(VS Code内置)
第二种:自定义Emmet snippets(通过JSON配置扩展)
第三种:预编译式Emmet(比如配合Post-HTML或Webpack loader)
听上去好像都挺高级,但真用起来差别可大了。
谁更灵活?谁更省事?
先说最常用的场景:快速写一个列表项结构。比如要做个用户卡片列表。
<ul class="user-list">
<li class="user-item">
<img src="avatar.jpg" alt="User Avatar">
<div class="user-info">
<h3 class="username">张三</h3>
<p class="bio">前端打工人</p>
</div>
</li>
</ul>
用原生Emmet怎么写?一行搞定:
ul.user-list>li.user-item>(img[src=avatar.jpg][alt="User Avatar"])+.user-info>h3.username+p.bio
敲完 Tab,直接生成。速度快到离谱,关键是不用切换上下文去查配置文件。
再看第二种:我自己写了个 snippets 叫 userCard,绑定到某个前缀。配置长这样:
"userListCard": {
"prefix": "ucard",
"body": [
"<ul class="user-list">",
" <li class="user-item">",
" <img src="$1" alt="User Avatar">",
" <div class="user-info">",
" <h3 class="username">$2</h3>",
" <p class="bio">$3</p>",
" </div>",
" </li>",
"</ul>"
],
"description": "用户卡片列表"
}
看起来不错对吧?输入 ucard 回车,也能出结构。但问题来了:
- 每个项目都得复制一遍这个 snippet
- 团队协作时别人没有这个配置,还得教他们装
- 改个结构要重新打开 snippets.json 编辑,不如直接写快
我试过在三个不同项目里维护这种 snippet,最后统一删了——太累。你不是在写代码,你是在伺候配置文件。
第三种更离谱:有人想让Emmet在构建时预处理。比如写个 .emmet 文件,然后用loader转成HTML。举个例子:
<!-- user-list.emmet -->
ul.user-list>li.user-item*3>img+div.user-info>h3.username{用户$}*3
然后通过一个webpack插件转成真实HTML。听着很酷,但真上项目你就知道多坑:
- 调试困难:浏览器报错显示的是转换后的行号,定位不到源文件
- 热更新延迟:改一下要等loader跑一圈
- 生态支持差:现在主流框架都不推荐这种DSL写法了
我之前在一个静态站项目里用了这种方案,结果每次改完刷新要等8秒……最后换成Pug了,但那是另一个故事了。
核心功能对比:别被花哨功能骗了
很多人觉得自定义方案“功能更多”,其实Emmet原生已经覆盖95%的日常需求了。来看看常用操作:
重复生成?用 * 就行:
li.item*5
生成带文本的内容?用 {}:
a[href="#"]{点击这里}
父子嵌套?用 >:
nav>ul>li*3>a[href="#"]
`>
<p>兄弟节点?用
+:</p></code></pre>plaintext
header+h1.title+p.desc
<pre class="pure-highlightjs line-numbers language-none"><code class="no-highlight language-none"><p>属性自动补全?class和id直接跟在后面:</p></code></pre>plaintext
div.container#main.content
<pre class="pure-highlightjs line-numbers language-none"><code class="no-highlight language-none"><p>变成:</p></code></pre>html
<div class="container content" id="main"></div>
<pre class="pure-highlightjs line-numbers language-none"><code class="no-highlight language-none"><p>这些操作我在日常开发中每天至少用几十次。关键是:它们是通用的。我去客户现场临时搭环境,只要装个VS Code,默认就有。不像某些snippet,还得导出导入,麻烦死了。</p>
<h2>踩坑提醒:这三个点我被坑过好几次</h2>
<p>1. 不要依赖 Emmet 生成完整组件逻辑</p>
<p>有一次我图快,用Emmet生成了一堆表单项,包括input type、label for、id绑定。结果后来加了个动态name字段,Emmet没法动态处理变量,只能手动改。从那以后我明白了:Emmet只适合静态结构,带逻辑的别硬套。</p>
<p>2. 注意空格陷阱</p>
<p>这个坑我踩了不止一次。看这段:</p></code></pre>plaintext
div .box
<pre class="pure-highlightjs line-numbers language-none"><code class="no-highlight language-none"><p>注意 div 和 .box 中间有个空格。你以为会生成
<div><div class="box"></div></div>?错,它会生成两个并列元素。正确的应该是:</p></code></pre>plaintext
div.box
<pre class="pure-highlightjs line-numbers language-none"><code class="no-highlight language-none"><p>少个空格,结果完全不一样。建议写完立刻预览一眼,别信直觉。</p>
<p>3. 特殊字符记得转义</p>
<p>比如你要生成带引号的属性:</p></code></pre>plaintext
a[title="点击'这里'"]
<pre class="pure-highlightjs line-numbers language-none"><code class="no-highlight language-none"><p>没问题。但如果里面还有双引号,就得小心了。亲测有效写法是用单引号包住值:</p></code></pre>plaintext
a[title='他说"你好"']
<pre class="pure-highlightjs line-numbers language-none"><code class="no-highlight language-none"><p>或者干脆避免复杂文本,后面手动补。</p>
<h2>我的选型逻辑:能少配就少配</h2>
<p>我现在选技术方案就一条原则:能不能开箱即用。</p>
<p>Emmet这种工具,本质是提效的,不是炫技的。你搞得越复杂,后期维护成本越高。尤其是当你换项目、换团队、换电脑的时候,最简单的反而最可靠。</p>
<p>所以我的选择很明确:用VS Code默认Emmet,不加任何额外配置。除非公司有统一规范要求,否则绝不搞自定义snippets。</p>
<p>那有人问:要不要装Emmet插件?答案是不需要。VS Code从1.5版本开始就把Emmet内建了,而且支持Vue、JSX、Svelte等各种语法上下文。你要是还单独装个Emmet插件,反而可能冲突。</p>
<p>顺带一提,WebStorm也内置了Emmet,行为几乎一致。这意味着你在不同IDE之间切换也不会断片。</p>
<h2>一点妥协:CSS那边我还是开了个例外</h2>
<p>虽然HTML坚决不用自定义,但CSS方面我给自己留了个后门。因为有些属性组合实在太长了,比如flex布局:</p></code></pre>css
display: flex;
align-items: center;
justify-content: space-between;
<pre class="pure-highlightjs line-numbers language-none"><code class="no-highlight language-none"><p>于是我配了个 snippet,前缀叫
fx:</p></code></pre>json
"Flex Center": {
"prefix": "fx",
"body": [
"display: flex;",
"align-items: center;",
"justify-content: ${1:center};"
]
}
`
<p>为什么这里肯配?因为:</p>
<ul>
<li>CSS结构稳定,很少变</li>
<li>属性组合高度重复</li>
<li>不会跨语言复用(不像HTML模板)</li>
</ul>
<p>算是我在实用主义面前的一点低头吧。</p>
<h2>以上是我的对比总结,有不同看法欢迎评论区交流</h2>
<p>说到底,Emmet只是个工具。别让它反过来控制你的工作流。我见过太多人花几小时优化编辑器配置,结果当天只写了两行业务代码,真的不值得。</p>
<p>如果你刚开始接触前端,听我一句劝:先把原生Emmet练熟,每天用,形成肌肉记忆。等你真遇到它解决不了的问题,再考虑扩展也不迟。</p>
<p>至于那些花里胡哨的预处理器+Emmet组合拳?放过自己吧。我们现在又不是在2012年写静态页,框架都帮你抽象好了结构,Emmet的任务就是帮你快速搭个原型,别的别指望太多。</p>
<p>最后贴个我常用的速记口诀,放快捷键旁边天天看:</p>
<ul>
<li>
> 子元素</li>
<li>+ 兄弟元素</li>
<li>* 重复次数</li>
<li>{} 文本内容</li>
<li>[] 自定义属性</li>
<li># id</li>
<li>.` class
记牢这几个,够用三年。其他的,边用边学就行。

暂无评论