1、编译作用域:
官方的解释是:父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译
例如:
Son.vue
- <template>
- <div>
- <h2>子组件</h2>
- <p>西安邮电大学</p>
- </div>
- </template>
- <script>
- export default {
- name: "Son",
- data(){
- return {
- isShow : true
- }
- }
- }
- </script>
Father.vue
- <template>
- <div>
- <son v-show="isShow"></son>
- </div>
- </template>
- <script>
- import Son from "@/components/Son";
- export default {
- name: "Father",
- data(){
- return {
- isShow: true
- }
- },
- components: {Son}
- }
- </script>
最终的结果是:父组件中的isShow为true,子组件的内容会显示;这是因为:使用的时候,子组件的使用过程是在父组件中出现的,作用域就是父组件,使用的属性也是属于父组件的属性。因此,isShow使用的父组件中的属性,而不是子组件的属性。
2、什么是插槽(slot)?
插槽(slot)将父组件的内容与子组件的模板相混合,从而弥补了视图的不足。如果父组件没有插入内容,那么 slot 的内容就作为默认出现;若父组件插入了内容,则 slot 的内容将被插入的内容替换掉。
3、为什么要使用插槽slot
插槽的目的在于:使组件更具有扩展性。例如,电脑预留的usb接口,可以用来连接多种外部设备,耳机、音响、U盘等等,使得更具有扩展性。插槽slot的作用正是如此,例如,组件中的一个地方,默认情况下为button,而在使用的时候,有需求需扩展为span,扩展为input,这时候就需要使用到插槽。
组件的封装方式(抽取共性,保留不同):就是将共性抽取到组件中,将不同暴露为插槽。一旦预留了插槽,就可以让使用者根据自己的需求,决定插槽中插入什么内容。是搜索框,还是文字,还是菜单。由调用者自己来决定。
4、插槽的使用
(1)匿名插槽(默认插槽):<slot></slot>,有且只有一个
Son.vue
- <template>
- <div>
- <h2>子组件</h2>
- <p>西安邮电大学</p>
- <slot></slot> <!-- 插槽 -->
- </div>
- </template>
-
- <script>
- export default {
- name: "Son"
- }
- </script>
Father.vue
- <template>
- <div>
- <son>
- <button>演示按钮</button> <!-- 放在插槽位置 -->
- </son>
- <son></son>
- </div>
- </template>
- <script>
- import Son from "@/components/Son";
- export default {
- name: "Father",
- components: {Son}
- }
- </script>
(2)具名插槽
当子组件的功能复杂时,子组件的插槽可能并非是一个。比如封装一个导航栏的子组件,可能就需要三个插槽,分别代表左边、中间、右边。那么,外面在给插槽插入内容时,如何区分插入的是哪一个呢?这时候,就需要给slot指定一个name属性,也就是具名插槽。
Son.vue
- <template>
- <div>
- <slot name="top"></slot><!-- 插槽 -->
- <h2>子组件</h2>
- <slot name="center"></slot><!-- 插槽 -->
- <p>西安邮电大学</p>
- <slot name="bottom"></slot><!-- 插槽 -->
- </div>
- </template>
-
- <script>
- export default {
- name: "Son"
- }
- </script>
Father.vue
- <template>
- <son>
- <template v-slot:top>
- <button>插槽演示</button>
- </template>
- <template v-slot:center>
- <input type="text"/>
- </template>
- <template #bottom> <!--具名插槽的简写-->
- <p>Vue3中插槽</p>
- </template>
- <template v-slot:default> <!--默认插槽-->
- <select>
- <option>A</option>
- <option>B</option>
- <option>C</option>
- </select>
- </template>
- </son>
- </template>
-
- <script>
- import Son from "@/components/Son";
- export default {
- name: "Father",
- components: {Son}
- }
- </script>
(3)作用域插槽
父组件在使用的时候可以替换slot插槽中的显示页面结构,但展示的数据还是来源于子组件。
例如:有一个需求,子组件中包括一组数据,比如:Languages: [‘JavaScript’, ‘Python’, ‘Swift’, ‘Go’, ‘C++’]
需要在多个界面进行展示:
A、某些界面以水平方向展示
B、某些界面以列表方式展示
Son.vue
- <template>
- <div>
- <h2>子组件</h2>
- <p>西安邮电大学</p>
- <slot :language="languageList"></slot>
- </div>
- </template>
-
- <script>
- export default {
- name: "Son",
- data(){
- return {
- languageList:['JavaScript','Python','Swift','Go','C++']
- }
- }
- }
- </script>
Father.vue
- <template>
- <div>
- <!--展示结构1:水平方向展示-->
- <son>
- <template slot-scope="slotProps">
- <h2>{{ slotProps.language.join('--')}}</h2>
- </template>
- </son>
- <!--展示结构2:列表形式展示-->
- <son>
- <template slot-scope="slotProps">
- <ul>
- <li v-for="(item,index) in slotProps.language" :key="index">{{ item }}</li>
- </ul>
- </template>
- </son>
- </div>
- </template>
-
- <script>
- import Son from "@/components/Son";
- export default {
- name: "Father",
- components: {Son}
- }
- </script>
5、v-slot指令
在 Vue2.6.0 中,为插槽引入了一个新的统一的语法 (即 v-slot 指令)。它取代了 slot 和 slot-scope 这两个目前已被废弃但未被移除且仍在使用的特性
(1)匿名插槽(默认插槽default)中使用v-slot指令
Son.vue
- <template>
- <div>
- <h2>子组件</h2>
- <p>西安邮电大学</p>
- <slot></slot>
- </div>
- </template>
-
- <script>
- export default {
- name: "Son"
- }
- </script>
Father.vue
- <template>
- <div>
- <son>
- <template v-slot:default>
- <button>匿名插槽演示</button>
- </template>
- </son>
- </div>
- </template>
-
- <script>
- import Son from "@/components/Son";
- export default {
- name: "Father",
- components: {Son}
- }
- </script>
(2)具名插槽中使用v-slot指令
Son.vue
- <template>
- <div>
- <slot name="top"></slot>
- <h2>子组件</h2>
- <slot name="center"></slot>
- <p>西安邮电大学</p>
- <slot name="bottom"></slot>
- </div>
- </template>
-
- <script>
- export default {
- name: "Son"
- }
- </script>
Father.vue
- <template>
- <div>
- <son>
- <template v-slot:center>
- <button>具名插槽演示</button>
- </template>
- </son>
- </div>
- </template>
-
- <script>
- import Son from "@/components/Son";
- export default {
- name: "Father",
- components: {Son}
- }
- </script>
(3)作用域插槽中使用v-slot指令
Son.vue
- <template>
- <div>
- <h2>子组件</h2>
- <p>西安邮电大学</p>
- <slot :language="languageList" name="xy"></slot>
- <slot :language="languageList" name="zf"></slot>
- </div>
- </template>
- <script>
- export default {
- name: "Son",
- data(){
- return {
- languageList:['JavaScript','Python','Swift','Go','C++']
- }
- }
- }
- </script>
Father.vue
- <template>
- <div>
- <!--展示结构1:水平方向展示-->
- <son>
- <template v-slot:zf="slotProps">
- <h2>{{ slotProps.language.join('--')}}</h2>
- </template>
- </son>
- <!--展示结构2:列表形式展示-->
- <son>
- <template v-slot:xy="slotProps">
- <ul>
- <li v-for="(item,index) in slotProps.language" :key="index">{{ item }}</li>
- </ul>
- </template>
- </son>
- </div>
- </template>
-
- <script>
- import Son from "@/components/Son";
- export default {
- name: "Father",
- components: {Son}
- }
- </script>