文章目录
- 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>
效果:
原理:会生成新的属性选择器。