文章目錄
- Vue3 組件
- 概述
- 根組件
- 定義和使用組件
- 樣式控制
- 全局樣式
- 局部樣式
- 深度樣式
Vue3 組件
概述
組件允許我們將 UI 劃分為獨立的、可重用的部分,并且可以對每個部分進行單獨的思考。在實際應用中,組件常常被組織成層層嵌套的樹狀結構:
根組件
我們傳入 createApp
的對象實際上是一個組件,每個應用都需要一個“根組件”,其他組件將作為其子組件。
如果你使用的是單文件組件,我們可以直接從另一個文件中導入根組件。
import { createApp } from 'vue'
// 從一個單文件組件中導入根組件
import App from './App.vue'const app = createApp(App)
定義和使用組件
在 src/components
目錄下定義 HelloWorld 組件:
<script setup >
import HelloWorldChild from "./HelloWorldChild.vue";
</script><template><h3>HelloWorld組件</h3><div>HelloWorld的div</div><p>aaaaaaaaaaaaaaa</p>
</template>
在 App 組件中使用:
<script setup>
import {ref} from "vue"
// 引入HelloWorld組件
import HelloWorld from "./components/HelloWorld.vue";const count = ref(0)
const incrementCount = () => {count.value++
}
</script><template><div><h2>App組件</h2><p>{{ count }}</p><button @click="incrementCount">count++</button><!--使用HelloWorld組件--><HelloWorld/></div>
</template>
效果:
樣式控制
全局樣式
在組件中定義的樣式,默認是全局有效的。
這是因為App組件的style標簽中的樣式,在打包后就會生成全局樣式,沒有額外添加其他的限制條件。因此App組件中的樣式既影響了當前組件的div,也影響了子組件的所有div和外部頁面中的div。
定義App組件:
<script setup>
import {ref} from "vue"
import HelloWorld from "./components/HelloWorld.vue";const count = ref(0)
const incrementCount = () => {count.value++
}
</script><template><div><h2>App組件</h2><p>{{ count }}</p><button @click="incrementCount">count++</button><HelloWorld/></div>
</template><style>
div {border: 1px solid red;margin: 20px;
}
</style>
定義HelloWorld組件:
<template><h3>HelloWorld組件</h3><div>HelloWorld的div</div>
</template>
效果:
局部樣式
Vue3 的 style 標簽中的樣式默認是全局的,但如果只針對某個組件內的標簽進行樣式控制,而不影響外部和內部子組件中標簽的樣式,可以在 style 標簽中添加 scoped 屬性,表示局部作用域樣式。
scoped 也就是 scoped = true
的簡寫。
修改子組件樣式:
<template><h3>HelloWorld組件</h3><div>HelloWorld的div</div><p>aaaaaaaaaaaaaaa</p>
</template><style scoped>
p {background: #ccc;
}
</style>
查看代碼結構:
scoped原理:
- 當組件添加 scoped 屬性后,該組件內的所有標簽都會自動添加
data-v-xxx
的屬性,表示唯一標識。 - 同時 style中定義的樣式選擇器中也會添加
data-v-xxx
的屬性標簽,這樣局部作用域的樣式只能影響當前組件。
深度樣式
如果想讓局部樣式影響子組件,可以使用 Vue3 提供的深度作用域選擇器 :deep()
。
定義 HelloWorldChild 組件:
<template><div><h4>HelloWorldChild組件</h4><p>HelloWorld的p標簽</p></div>
</template>
在 HelloWorld 組件中使用:
<script setup>
import HelloWorldChild from "./HelloWorldChild.vue";
</script><template><div><h3>HelloWorld組件</h3><div>HelloWorld的div</div><p>HelloWorld的p標簽</p><HelloWorldChild/></div>
</template><style scoped>
div p {background: #ccc;
}div h4 {color: red;
}
</style>
效果:
因為 HelloWorld 組件使用 scoped 屬性,因此 div p
和 div h4
的樣式沒有出現 HelloWorldChild 子組件中。
在 HelloWorld 組件中使用 :deep()
選擇器:
<style scoped>
div :deep(p) {background: #ccc;
}div :deep(h4) {color: red;
}
</style>
效果:
原理:會生成新的屬性選擇器。