今天晚上,我在某個組件裏看到了這樣一段代碼,簡化來講,大概長這樣:
// Child.vue
<template v-if="false">
<div>Foo</div>
</template>
// Parent.vue
<template>
<Child />
</template>
按理來說,這裏應該什麼都不出現,但是子組件裏的Foo卻正常顯示了。換成下面兩種寫法組件就能正常隱藏了。
第一種:
// Child.vue
<template>
<div v-if="false">Foo</div>
</template>
// Parent.vue
<template>
<Child />
</template>
第二種:
// Child.vue
<template>
<div>Foo</div>
</template>
// Parent.vue
<template>
<Child v-if="false"/>
</template>
我一開始懷疑是template的問題,但是官方文檔有使用template的寫法:
因爲
v-if
是一個指令,所以必須將它添加到一個元素上。但是如果想切換多個元素呢?此時可以把一個元素當做不可見的包裹元素,並在上面使用
v-if。最終的渲染結果將不包含
元素。<template v-if="ok"> <h1>Title</h1> <p>Paragraph 1</p> <p>Paragraph 2</p> </template>
後來看了一下vue-loader的文檔,發現了這麼一段:
模板
- 每個
.vue
文件最多包含一個<template>
塊。- 內容將被提取並傳遞給
vue-template-compiler
爲字符串,預處理爲 JavaScript 渲染函數,並最終注入到從<script>
導出的組件中。
意思是,單文件組件的template相當於是一個標明需要交給Vue的渲染函數進行處理的內容範圍的佔位符,webpack處理的時候會直接提取出最外層template內的內容,忽略掉template這個標籤本身,所以寫在template上的屬性和指令都是沒有用的。
那爲什麼寫在裏面的template就能用呢?因爲這兩個根本不是一個東西,只是正好同名了而已。最外面的那個只是一個佔位符,裏面的則有實際的用途。