Vue 的 v-cloak 和 v-pre 指令有什么作用?

{{ userName }} 直接露在页面上,这个锅我见过不止一次。
页面一刷新,接口还没回来,Vue 还没接管 DOM,用户先看到一坨模板语法。等一两百毫秒后页面又正常了。测试环境没人管,到了线上低端机、弱网、后台管理系统首屏一堆资源加载时,这个问题就很扎眼。
这个时候才该想起 v-cloak。
v-cloak 不是用来优化性能的,也不是让 Vue 渲染更快的。它干的事很土:Vue 没编译完之前,把这块 DOM 先藏起来。Vue 实例挂载完成后,这个属性会被移除,CSS 失效,页面再显示出来。
最常见写法就这样:
const appHtml = `
<div id="app" v-cloak>
<span>用户:{{ profile.name }}</span>
<span>余额:{{ wallet.amount }}</span>
</div>
`
document.body.innerHTML = appHtml
const style = document.createElement('style')
style.innerHTML = `
[v-cloak] {
display: none;
}
`
document.head.appendChild(style)
Vue.createApp({
data() {
return {
profile: { name: '加载中' },
wallet: { amount: '--' }
}
},
mounted() {
setTimeout(() => {
this.profile.name = '老周'
this.wallet.amount = '86.50'
}, 300)
}
}).mount('#app')
这段代码里,关键不是 mounted,关键是 [v-cloak] { display: none; }。
很多人只写了:
<div id="app" v-cloak>
然后发现没效果。
这地方我一般先看 CSS。v-cloak 本身不会帮你隐藏,它只是挂在 DOM 上的一个标记。你不写 CSS,它就跟没写差不多。
还有一点要注意,v-cloak 更适合 CDN 方式引 Vue 的老项目,或者页面里直接写模板的场景。现在很多工程化项目,模板会被构建工具提前编译,首屏看到 {{ xxx }} 的概率小很多。不是不能用,是用处没那么大。
真正容易踩的是这种后台页面:
document.body.innerHTML = `
<div id="app" v-cloak>
<div class="card">订单数:{{ stat.orderCount }}</div>
<div class="card">退款数:{{ stat.refundCount }}</div>
</div>
`
Vue.createApp({
data() {
return {
stat: {
orderCount: 0,
refundCount: 0
}
}
},
async mounted() {
const res = await fetch('/api/dashboard/stat')
this.stat = await res.json()
}
}).mount('#app')
接口慢不慢,跟 v-cloak 没直接关系。它管的是 Vue 接管 DOM 之前那一小段空窗期。接口慢了,页面会显示默认值或者 loading;Vue 还没启动,才会露出 {{ stat.orderCount }}。
再看 v-pre。
v-pre 正好是另一个方向:这块内容你别编译,原样显示。
比如写一个文档页,要展示 Vue 模板语法:
document.body.innerHTML = `
<div id="app">
<h3>模板示例</h3>
<pre v-pre>
<span>{{ user.name }}</span>
<button @click="saveUser">保存</button>
</pre>
<p>当前用户:{{ currentUser }}</p>
</div>
`
Vue.createApp({
data() {
return {
currentUser: 'admin'
}
}
}).mount('#app')
这里我就会直接给 pre 加 v-pre。
不加的话,Vue 会把 {{ user.name }} 当成真正的绑定去解析。轻则页面展示不对,重则控制台一堆告警。尤其是做低代码配置页、组件文档页、模板编辑器时,这个指令挺有用。
v-pre 还有一个小用途:跳过大量不需要编译的静态内容。
document.body.innerHTML = `
<div id="app">
<div v-pre class="license">
这里是一大段固定协议文本。
里面就算出现 {{ companyName }},也不要当成 Vue 变量。
</div>
<button @click="confirm">同意</button>
</div>
`
Vue.createApp({
methods: {
confirm() {
console.log('user confirmed')
}
}
}).mount('#app')
不过别指望它救性能。页面上真有几千行静态内容,问题大概率不在 v-pre,而在你为什么把这么一坨东西塞进 Vue 管的区域里。
这两个指令放一起看,其实很好分。
v-cloak 是“先别露出来,等 Vue 编译完”。
v-pre 是“这块别编译,我就想原样显示”。
我见过有人把 v-pre 当成防闪烁用,结果页面里的变量永远不更新:
document.body.innerHTML = `
<div id="app" v-pre>
用户名:{{ name }}
</div>
`
Vue.createApp({
data() {
return {
name: '东哥'
}
}
}).mount('#app')
这代码看一眼就不对。v-pre 放在 #app 上,相当于告诉 Vue:整个根节点下面都别解析。那你还挂 Vue 干什么。
正常应该是:
document.body.innerHTML = `
<div id="app" v-cloak>
用户名:{{ name }}
<pre v-pre>
页面里可以这样写:{{ name }}
</pre>
</div>
`
外层用 v-cloak 防止模板闪出来,里面需要展示模板源码的地方用 v-pre 保留原样。
这俩指令都不复杂,但挺能看出项目是不是糙。
页面一闪,先查 v-cloak 有没有配 CSS。
模板源码被 Vue 吃掉,先查该不该加 v-pre。
别反着用。反着用,排查半天,最后发现不是 Vue 坑你,是你给 Vue 下了个错误命令。
以上关于Vue 的 v-cloak 和 v-pre 指令有什么作用?的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » Vue 的 v-cloak 和 v-pre 指令有什么作用?
微信
支付宝