class 8: vue.js 3组件化基础(1)

组件的嵌套

  • 当我们用脚手架搭建了一个vue项目之后,可以简单看看它的结构,src中的main.js是它的启动入口,文件内容如下
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')
  • 首先导入根组件(App组件),然后调用createApp函数创建Vue的实例,最后调用mount函数将页面渲染到index.html文件中id="app"<div>元素上,这一步是将Vue的元素app挂载到DOM上,app元素对应的是App.vue文件,这个文件内容如下。当项目运行起来之后,显示在页面上的就将会是这个文件的template标签内的元素
<!--App.vue-->
<template>
  <div>
<!--    页面头部内容-->
    <div class="header">
      <h4>Header</h4>
      <h4>NavBar</h4>
    </div>
  </div>
  <div class="main">
<!--    页面中间内容-->
    <h4>Banner轮播图内容</h4>
    <ul>
      <li>商品信息1</li>
      <li>商品信息2</li>
      <li>商品信息3</li>
      <li>商品信息4</li>
      <li>商品信息5</li>
    </ul>
  </div>
<!--  页面尾部内容-->
  <div class="footer">
    <h4>Footer</h4>
  </div>
</template>

<script>
export default {
  name: 'App',
  components: {}
}
</script>

<style>
.header, .main, .footer{
  border: 1px solid#999;
  margin-bottom: 4px;
}
</style>

  • 上面代码将所有逻辑都放到了根组件中,虽然可以实现功能,但是不符合组件化开发的思想,我们应该把大的组件进行拆分,拆成一个个具有独立功能的小组件,然后将这些组件组合或嵌套在一起,构成应用程序。如下图所示
    在这里插入图片描述
  • 重构后的代码结构如下
<!--Header.vue-->
<template>
  <div>
    <div class="header">
      <h4>Header</h4>
      <h4>NavBar</h4>
    </div>
  </div>
</template>

<style scoped>
  .header{
    border: 1px solid#999;
    margin-bottom: 4px;
  }
</style>
<!--Footer.vue-->
<template>
  <div class="footer">
    <h4>Footer</h4>
  </div>
</template>

<style scoped>
  .footer {
    border: 1px solid#999;
    margin-bottom: 4px;
  }
</style>
<!--Main.vue-->
<template>
  <div class="main">
    <main-banner></main-banner>
    <main-product-list></main-product-list>
  </div>
</template>

<style scoped>
  .main {
    border: 1px solid #999;
    margin-bottom: 4px;
  }
</style>
<script setup lang="ts">
import MainBanner from "@/chapters/chapter02/MainBanner.vue";
import MainProductList from "@/chapters/chapter02/MainProductList.vue";
</script>
<!--MainBanner.vue-->
<template>
  <h4>Banner轮播图内容</h4>
</template>

<style scoped>

</style>
<!--MainProductList.vue-->
<template>
  <ul>
    <li>商品信息1</li>
    <li>商品信息2</li>
    <li>商品信息3</li>
    <li>商品信息4</li>
    <li>商品信息5</li>
  </ul>
</template>

<style scoped>

</style>
<script setup lang="ts">
</script>
<!--App.vue-->
<template>
  <div class="app">
    <Header></Header>
    <Main></Main>
    <Footer></Footer>
  </div>
</template>

<style scoped>

</style>
<script setup lang="ts">
import Header from "@/chapters/chapter02/Header.vue";
import Footer from "@/chapters/chapter02/Footer.vue";
import Main from "@/chapters/chapter02/Main.vue";
</script>
  • main.js中引入上面App组件,如下
// main.js
import { createApp } from 'vue'
import App from './chapters/chapter02/App.vue'
// import App from './App.vue'

createApp(App).mount('#app')
  • 运行可以发现,重构后的代码效果与之前是相同的

组件样式

  • 有几种用于编写单文件组件的样式,下面分别用例子演示

Scoped CSS

  • <style scoped>是Vue.js 3中的一个样式作用域标记。在一个带有scoped标记的<style>标签中定义的样式仅在当前组件中生效,并且Vue.js 3会自动将选择器变异成带有唯一属性的选择器,以免和其他组件中的样式冲突。通常,我们将其称为组件的局部样式
  • 当单文件组件(SFC)的style标签带有scope属性时,表示在该标签中编写的样式都是局部样式,它的CSS只会应用到当前组件的元素上。这些CSS最终会被PostCSS转换,如下图
    在这里插入图片描述
  • 上面data-*是HTML5提供的数据属性特性,具体可查下HTML5文档了解

局部样式的泄露

看下面这个例子

<template>
  <h4>App Title</h4>
  <HelloWorld></HelloWorld>
</template>

<script setup lang="ts">
import HelloWorld from "@/chapters/chapter03/HelloWorld.vue";
</script>

<style scoped>
h4{
  text-decoration: underline;
}
</style>

<template>
  <h4>Hello World!</h4>
</template>

<style scoped>

</style>
  • 实现的效果如下图所示
    在这里插入图片描述
  • 也就是说,h4样式从父组件中泄漏到子组件HelloWorld中了。为了解决这个问题,有一些办法,最简单的办法是减少标签选择器的使用,转而使用class选择器,保证class选择器的唯一性,比如下面这样
<template>
  <h4 class="hello-world">App Title</h4>
  <HelloWorld></HelloWorld>
</template>

<script setup lang="ts">
import HelloWorld from "@/chapters/chapter03/HelloWorld.vue";
</script>

<style scoped>
.hello-world{
  text-decoration: underline;
}
</style>

在这里插入图片描述

  • 可以看到这样写父组件的样式没有泄露到子组件中,因为我们使用了class选择器

深度选择器

  • 有时我们需要通过修改父组件的局部样式中修改子组件中某个元素的样式,这时,我们可以使用深度选择器:deep()这个伪类来实现,下面展示:deep()的使用
  • 我们把上面的文件改成下面这样
<template>
  <h4>Hello World!</h4>
  <h4 class="msg">My message</h4>
</template>

<style scoped>
.msg {
  
}
</style>
  • 现在的效果如下
    在这里插入图片描述
  • 我们来通过:deep()来通过父组件来修改子组件的class选择器msg,如下
<template>
  <div class="hello-world">
    <h4>App Title</h4>
    <HelloWorld></HelloWorld>
  </div>
</template>

<script setup lang="ts">
import HelloWorld from "@/chapters/chapter03/HelloWorld.vue";
</script>

<style scoped>
:deep(.msg) {
  text-decoration: underline;
}
</style>
<template>
  <h4>Hello World!</h4>
  <h4 class="msg">My message</h4>
</template>

<style scoped>
</style>
  • 现在的效果如下
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clarence Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值