Vue3——组件基础

组件详解

1、组件样式控制

1.1、组件定义与使用

html 复制代码
<template>
  <div>
    <h2>App组件标题</h2>
    <p>count:{{ count }}</p>
    <button @click="increment">增加</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);
    const increment = () => {
      count.value++;
    };

    return {
      count,
      increment
    }
  }
}
</script>

<style>
p {
  background: #ccc;
}
</style>

App.vue是项目根组件文件,下面尝试定义子组件文件并嵌套在App.vue中。比如在components目录下定义HelloWorld.vue子组件文件。值得一提的是,Vue组件文件中可以缺少script、template、style中的任意一个部分,程序不会报任何错误。

components/HelloWorld.vue文件代码如下。

html 复制代码
<template>
  <div>
    <h3>HelloWorld组件标题</h3>
    <div>内部div内容</div>
  </div>
</template>

在App.vue的script中引入components/HelloWorld.vue组件文件,并直接在template中使用HelloWorld组件标签。值得一提的是,之所以能在template中直接使用HelloWorld组件标签,是因为在import引入组件后,Vue会自动注册此组件。

修改后的App.vue文件代码如下。

html 复制代码
<template>
  <div>
    <h2>App组件标题</h2>
    <p>count:{{ count }}</p>
    <button @click="increment">增加</button>
    <HelloWorld/>
  </div>
</template>

<script setup>
  import HelloWorld from './components/HelloWorld.vue';
  import { ref } from 'vue';

  const count = ref(0);
  const increment = () => {
    count.value++;
  };
</script>

<style>
p {
  background: #ccc;
}
</style>

1.2、全局样式控制

在组件中定义的样式,默认是全局有效的。也就是说,其可以作用于当前组件中的标签、子组件的根标签及外部的标签。下面我们来测试一下,给App组件的style标签添加全局样式,代码如下。

css 复制代码
div {
  border: 1px solid #aaa;
  margin: 20px;
}

添加全局样式后的页面效果如图所示。

从图中可以看出,App组件中的样式既影响了当前组件的div,也影响了子组件的所有div和外部页面中的div。

产生该效果的原因也非常简单,因为App组件的style标签中的样式,在打包后就会生成全局样式,没有额外添加其他的限制条件。

1.3、局部作用域样式控制

在App组件的style标签中添加scoped属性,不需要为其指定属性值,它的本质是"scoped="true""的简写方式,在项目开发中我们采用的都是简写方式,如下所示。

html 复制代码
<style scoped>

只修改App组件的style标签,内部的其余样式不做任何修改,修改代码后的页面效果和代码结构如图所示。

从页面效果可以看出,此时的样式只影响当前组件的div和子组件HelloWorld的根标签div,而不再影响子组件的子标签div和外部的div。由此可以得出局部作用域样式的特点:只作用于当前组件的所有标签和子组件的根标签

局部作用域样式的原理其实并不复杂,其内部主要做了两件事:

  1. 一旦style声明为scoped,当前组件的所有标签和子组件的根标签就都会自动添加名为data-v-xxx的唯一标识属性。
  2. 在项目打包运行的页面中,style中的样式选择器的最右侧添加了名为data-v-xxx的属性选择器。这就让局部作用域样式只能作用于带data-v-xxx属性的标签,而此时只有当前组件的标签和子组件的根标签带有此属性,子组件的子标签和外部标签都没有此属性,因此局部作用域样式就只能影响当前组件的标签和子组件的根标签。

1.4、深度样式控制

如何能让组件的局部样式(也就是局部作用域样式)影响子组件的子标签呢?这就需要使用Vue提供的深度作用域选择器来实现。代码其实很简单,只需要将需要进行深度选择的标签用"​:deep(​)​"来包含,它就能匹配并影响子组件的子标签。

比如,我们想在App组件的局部作用域样式中,改变HelloWorld子组件的子标签h3的样式,那么可以在App组件中编写如下代码。

html 复制代码
<style scoped>
p {
  background: #ccc;
}
div {
  border: 1px solid #aaa;
  margin: 20px;
}
div h3 {
  font-size: 40px;
}
</style>

但在运行项目后,开发者会发现标题文字并没有变大,也就是样式没有影响HelloWorld子组件的子标签h3。原因即局部作用域样式是不能作用到子组件的子标签的,此时可以使用深度作用域选择器来实现,也就是使用"​:deep(​)​"来包含h3,代码如下。

csss 复制代码
div :deep(h3) {
  font-size: 40px;
}

此时样式已经作用到子组件的子标签h3上了,页面效果如图所示。

深度作用域选择器的原理是什么呢?我们来看一下打包生成的样式就可以知道了,如下所示。

其本质就是将最右侧的属性选择器移动到了deep声明的左侧,这也就意味着整个属性选择器对目标元素没有了属性的要求,这样就可以成功匹配子组件的子标签了。

2、组件通信之props

2.1、组件关系

在App父组件(根组件)中嵌套了HelloWorld子组件。这就意味着Vue的组件是可以互相嵌套的。那么这样的嵌套是一定存在层次关系的,嵌套组件之间也一定存在沟通和信息传递。

2.1.1、父与子关系模式

在App组件中嵌套了HelloWorld子组件,那么相对于HelloWorld子组件而言,App就是它的父组件,因此父与子关系模式是从上到下的,如图所示。

2.1.2、子与父关系模式

将App父组件与HelloWorld子组件的关系换一个视角,从HelloWorld子组件的角度来看App父组件,就变成了从下到上的子与父关系模式,如图所示。

2.1.3、祖与孙关系模式

父下会有子,而子又会再包含子,因此父与孩子的孩子之间的关系就变成了祖孙关系,并且除了祖与孙,还会存在祖与曾孙、祖与玄孙等更深层次的关系。值得一提的是,只要超过了父子,孙、曾孙、玄孙都可以简化为祖与孙关系模式,如图所示。

2.1.4、其他关系(非父子与祖孙)模式

当然父组件可能会包含一个子组件,也可能会包含多个子组件,而子组件中仍旧可能会存在孙、曾孙、玄孙等更深层级的嵌套子组件,那么从横向视角来看,子组件2与子组件1、子组件2与孙组件1、孙组件2与曾孙组件1等关系就成了更为复杂的跨越父与子、祖与孙单向顺序的非父子与祖孙关系模式,如图所示。

相关推荐
恋猫de小郭1 小时前
Jetpack Compose 1.11 正式版发布,下一代的全新控件和样式 API,你必须知道
android·前端·flutter
孩子 你要相信光1 小时前
前端 Canvas 导出带水印图片跨域问题
前端
zxna2 小时前
前端直连oss分片上传文件,断点续传
前端
Southern Wind2 小时前
Vue 3 + Socket.io 实时聊天项目完整开发文档
前端·javascript·vue.js
甄心爱学习2 小时前
【项目实训(个人4)】
前端·vue.js·python
轮子大叔2 小时前
HTML入门
前端·html
skilllite作者2 小时前
SkillLite 技术演进笔记:Workspace、沙箱与进化
java·开发语言·前端·笔记·安全·agentskills
qq_419854052 小时前
clip-path绘制倾斜角裁剪的矩形占比条;基于svg实现仪表盘弧线占比图。
前端·javascript·vue.js
m0_738120722 小时前
渗透基础知识ctfshow——Web应用安全与防护(完结:第八章)
前端·python·sql·安全·web安全·网络安全