Vue3——组件基础
组件详解1、组件样式控制1.1、组件定义与使用1.2、全局样式控制1.3、局部作用域样式控制1.4、深度样式控制2、组件通信之props2.1、组件关系2.1.1、父与子关系模式2.1.2、子与父关系模式2.1.3、祖与孙关系模式2.1.4、其他关系非父子与祖孙模式1、组件样式控制1.1、组件定义与使用templatedivh2App组件标题/h2pcount:{{ count }}/pbuttonclickincrement增加/button/div/templatescriptimport{ref}fromvue;exportdefault{setup(){constcountref(0);constincrement(){count.value;};return{count,increment}}}/scriptstylep{background:#ccc;}/styleApp.vue是项目根组件文件下面尝试定义子组件文件并嵌套在App.vue中。比如在components目录下定义HelloWorld.vue子组件文件。值得一提的是Vue组件文件中可以缺少script、template、style中的任意一个部分程序不会报任何错误。components/HelloWorld.vue文件代码如下。templatedivh3HelloWorld组件标题/h3div内部div内容/div/div/template在App.vue的script中引入components/HelloWorld.vue组件文件并直接在template中使用HelloWorld组件标签。值得一提的是之所以能在template中直接使用HelloWorld组件标签是因为在import引入组件后Vue会自动注册此组件。修改后的App.vue文件代码如下。templatedivh2App组件标题/h2pcount:{{ count }}/pbuttonclickincrement增加/buttonHelloWorld//div/templatescriptsetupimportHelloWorldfrom./components/HelloWorld.vue;import{ref}fromvue;constcountref(0);constincrement(){count.value;};/scriptstylep{background:#ccc;}/style1.2、全局样式控制在组件中定义的样式默认是全局有效的。也就是说其可以作用于当前组件中的标签、子组件的根标签及外部的标签。下面我们来测试一下给App组件的style标签添加全局样式代码如下。div{border:1px solid #aaa;margin:20px;}添加全局样式后的页面效果如图所示。从图中可以看出App组件中的样式既影响了当前组件的div也影响了子组件的所有div和外部页面中的div。产生该效果的原因也非常简单因为App组件的style标签中的样式在打包后就会生成全局样式没有额外添加其他的限制条件。1.3、局部作用域样式控制在App组件的style标签中添加scoped属性不需要为其指定属性值它的本质是“scoped“true””的简写方式在项目开发中我们采用的都是简写方式如下所示。stylescoped只修改App组件的style标签内部的其余样式不做任何修改修改代码后的页面效果和代码结构如图所示。从页面效果可以看出此时的样式只影响当前组件的div和子组件HelloWorld的根标签div而不再影响子组件的子标签div和外部的div。由此可以得出局部作用域样式的特点只作用于当前组件的所有标签和子组件的根标签。局部作用域样式的原理其实并不复杂其内部主要做了两件事:一旦style声明为scoped当前组件的所有标签和子组件的根标签就都会自动添加名为data-v-xxx的唯一标识属性。在项目打包运行的页面中style中的样式选择器的最右侧添加了名为data-v-xxx的属性选择器。这就让局部作用域样式只能作用于带data-v-xxx属性的标签而此时只有当前组件的标签和子组件的根标签带有此属性子组件的子标签和外部标签都没有此属性因此局部作用域样式就只能影响当前组件的标签和子组件的根标签。1.4、深度样式控制如何能让组件的局部样式也就是局部作用域样式影响子组件的子标签呢这就需要使用Vue提供的深度作用域选择器来实现。代码其实很简单只需要将需要进行深度选择的标签用“deep”来包含它就能匹配并影响子组件的子标签。比如我们想在App组件的局部作用域样式中改变HelloWorld子组件的子标签h3的样式那么可以在App组件中编写如下代码。stylescopedp{background:#ccc;}div{border:1px solid #aaa;margin:20px;}div h3{font-size:40px;}/style但在运行项目后开发者会发现标题文字并没有变大也就是样式没有影响HelloWorld子组件的子标签h3。原因即局部作用域样式是不能作用到子组件的子标签的此时可以使用深度作用域选择器来实现也就是使用“deep”来包含h3代码如下。div :deep(h3) { font-size: 40px; }此时样式已经作用到子组件的子标签h3上了页面效果如图所示。深度作用域选择器的原理是什么呢我们来看一下打包生成的样式就可以知道了如下所示。其本质就是将最右侧的属性选择器移动到了deep声明的左侧这也就意味着整个属性选择器对目标元素没有了属性的要求这样就可以成功匹配子组件的子标签了。2、组件通信之props2.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等关系就成了更为复杂的跨越父与子、祖与孙单向顺序的非父子与祖孙关系模式如图所示。