vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令

目录

一、初识组件

1.1 什么是组件?什么是组件化?

1.2 Vue中如何创建组件?

1.3 组件内的 scoped 是如何工作的?

1.4 组件切换

1.5 动态组件--component

1.6 组件缓存--keep-alive

1.7 异步组件

二、组件动画

2.1 如何给组件添加动画 ?

2.2 组件动画示例

三、父子组件

3.1 什么是父子组件?

3.2 父传子--数据传递(props)

3.3 父传子--配合循环

3.4 单向数据流

3.5 子传父--$emit

3.6 子传父--数据传递

3.7 子传父之sync(语法糖)

3.8 命名注意点

四、跨组件传值及多级传递

4.1 跨组件传值--EventBus

4.2 数据和方法的多级传递

五、组件插槽--v-slot指令

5.1 什么是v-slot指令?

 5.2 使用 slot-scope 接收数据

 六 、匿名插槽

七 、具名插槽

7.1 初识具名插槽

7.2 示例

八、作用域插槽

8.1 初识作用域插槽

8.2 其他应用场景

ii. 自定义组件内标签+内容

九、自定义指令

9.1 初识自定义指令

9.2 使用只定义指令进行传值

 


 

一、初识组件

1.1 什么是组件?什么是组件化?

组件:可复用的vue实例, 通过封装其标签, 样式,和 JS代码

组件化:封装的思想,把页面上‘可重用的部分’封装为‘组件’,从而方便项目的开发和维护

例如:把一个很大的界面拆分为多个小的界面,每一个小的界面就是一个组件,将大界面拆分成小界面就是组件化

vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第1张图片

组件化的好处:

独立作用域

可以简化Vue实例代码

可以提高代码的复用性


1.2 Vue中如何创建组件?

每个组件都是一个独立的个体,代码里体现为一个独立的 .vue 文件

  • 1.创建组件即创建一个 .vue 文件,封装要复用的标签、样式以及JS代码
  • 2.引入并注册已经创建好的组件
  • 3.在需要用到组件的.vue文件里直接使用即可
  • 使用:把组件名当做标签使用即可

全局注册(全局组件)--main.js里进行如下配置:

在任何一个Vue实例控制的区域中都可以使用

import Vue from 'vue'
import 组件对象 from 'vue文件路径'

Vue.component('组件名', 组件对象)
<组件名>

局部注册(局部组件) -- 在需要用到组件的那个 .vue 文件里配置:

只能在自定义的那个Vue实例控制的区域中使用

import 组件对象 from 'vue文件路径'

export default {
    components: {
     "组件名": 组件对象
  }
}
<组件名>

注意点:组件文件名/组件名 都以“大写”英文开头

运行:将组件标签换成对应封装的真实标签显示


1.3 组件内的 scoped 是如何工作的?

在当前组件内标签都被随机的添加 data-v-hash值 的属性

vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第2张图片

css选择器都被添加 [data-v-hash值] 的属性选择器

Vue组件内样式, 只针对当前组件内标签生效如何做?

在style上添加scoped,webpack在打包的时候便会自动给标签添加data-v-hash值属性, 而且所有CSS的选择都会自动加上一个属性选择器


1.4 组件切换

对于普通元素我们可以通过v-if来实现切换

对于组件我们也可以通过v-if来实现切换,因为组件的本质就是一个自定义元素

我是首页


vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第3张图片


1.5 动态组件--component

什么是动态组件?

在同一个挂载点, 可以切换显示不同组件

如何使用动态组件?

vue内置的component组件, 配合is属性

如何切换?

改变is属性的值, 为要显示的组件名即可 

通过v-if/v-else-if/v-else确实能够切换组件,但是在Vue中切换组件还有另一种更专业的方式,那就是动态组件:

根据数据的变化,结合 component 这个标签,来随时动态切换组件

 

步骤:

  1. 创建要被切换的组件--标签+样式
  2. 引入到要展示的vue文件内并注册
  3. 在该vue文件内通过变量来承载要显示的组件名
  4. 设置挂载点
  5. 通过按钮点击实现切换

App.vue



UserDynamic.vue



UserName.vue



UserInfo.vue



vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第4张图片

 


1.6 组件缓存--keep-alive

频繁的切换组件会导致组件频繁地创建和销毁,性能是不高的,那么如何避免呢?

 

vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第5张图片 

 

component可以配合keep-alive来保存被隐藏组件隐藏之前的状态

如何进行组件缓存?

vue内置的keep-alive组件把要缓存的组件包起来

组件缓存好处?

不会频繁的创建和销毁组件, 页面更快呈现

 

keep-alive的用法:

参数:

  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存
  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存
  • max - 数字。最多可以缓存多少组件实例

包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 相似, 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中

当组件在 内被切换,它的 activateddeactivated 这两个生命周期钩子函数将会被对应执行

是用在其一个直属的子组件被开关的情形。如果你在其中有 v-for 则不会工作

includeexclude prop 允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示:

App.vue,



info.vue,




me.vue,



vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第6张图片


1.7 异步组件

 在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块

为了简化,Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义

Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染

App.vue






AComponent.vue





BComponent.vue






ErrorComponent.vue





vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第7张图片

点击“切换”按钮后,

 vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第8张图片


二、组件动画

2.1 如何给组件添加动画 ?

给组件添加动画和过去给元素添加动画一样,如果是单个组件就使用transition;如果是多个组件就使用transition-group

过渡动画注意点:

默认情况下进入动画和离开动画是同时执行的,如果想一个做完之后再做另一个,需要指定动画模式

同时生效的进入和离开的过渡不能满足所有要求,所以 Vue 提供了过渡模式

  • in-out:新元素先进行过渡,完成之后当前元素过渡离开。

  • out-in:当前元素先进行过渡,完成之后新元素过渡进入。

2.2 组件动画示例

        .v-enter {
            opacity: 0;
            margin-left: 300px;
        }
        
        .v-enter-to {
            opacity: 1;
        }
        
        .v-enter-active {
            transition: all 3s;
        }
        
        .v-leave {
            opacity: 1;
        }
        
        .v-leave-to {
            opacity: 0;
        }
        
        .v-leave-active {
            transition: all 3s;
            margin-left: 300px;
        }


三、父子组件

3.1 什么是父子组件?

在一个组件中又定义了其他组件就是父子组件,其实局部组件就是简单的父子组件,因为我们说过可以把Vue实例看作一个大组件

我们在Vue实例中定义了局部组件,就相当于在大组件里定义了小组件

谁被引入了谁就是“儿子”即子组件

如何定义其他的父子组件?

自定义组件中可以使用data,可以使用methods。当然自定义组件也可以使用components,所以我们也可以在自定义组件中再定义其他组件

注意:

子组件只能在定义它的父组件里面使用

App.vue




info.vue,






vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第9张图片


3.2 父传子--数据传递(props)

父子组件传递?

在Vue中子组件是不能访问父组件里的数据的,如果子组件想要访问父组件的数据,必须通过父组件传递

如何传递?

  1. 在父组件中通过v-bind传递数据(v-bind:自定义接收名称="要传递的数据")
  2. 在子组件中通过props接收数据(props:["自定义接收名称"])

props:组件之间的数据交互

单向数据流:自上而下的传递

 数组和对象的默认写法:default:[]-->工厂模式

数字和字符串可以直接写:default:0

info.vue,






App.vue,



vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第10张图片


3.3 父传子--配合循环

info.vue,






App.vue,




vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第11张图片

循环使用组件注意事项?
每次循环, 变量和组件, 都是独立的 


3.4 单向数据流

子组件内能改变, 父传入的数据吗?  能,但是不推荐

从父到子的数据流向, 叫单向数据流

子组件修改, 不通知父级, 造成数据不一致性

Vue规定props里的变量, 本身是只读的

info.vue,





App.vue,




vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第12张图片

 此时会报如下错误:

vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第13张图片


3.5 子传父--$emit

父子组件方法传递?

在Vue中子组件是不能访问父组件的方法的,如果子组件想访问父组件的方法,必须通过父组件传递

如何传递?

父组件内  <子组件 @自定义事件名="父methods里的函数名" />

子组件:this.$emit('自定义事件名', 值)

示例1:

App.vue,



info.vue,



vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第14张图片

示例2:

App.vue



info.vue





vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第15张图片

什么时候使用子传父技术?
当子想要去改变父里的数据
 

子传父如何实现?
父组件内, 给组件@自定义事件="父methods函数"
子组件内, 恰当时机this.$emit('自定义事件名', 值) 


3.6 子传父--数据传递

如何传递?

既然我们可以将父组件的方法传递给子组件,我们可以在子组件里调用父组件中的方法,那么我们就可以在调用方法的时候给方法传递参数,传递的参数就是我们需要传递的数据

App.vue,



info.vue,



vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第16张图片


3.7 子传父之sync(语法糖)

 在子元素中修改父元素中的数据,可以使用.sync形式处理

在有些情况下,我们可能需要对一个 prop 进行“双向绑定”

不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以变更父组件,且在父组件和子组件两侧都没有明显的变更来源。

这也是为什么我们推荐以 update:myPropName 的模式触发事件取而代之

然后父组件可以监听那个事件并根据需要更新一个本地的数据 property

为了方便起见,我们为这种模式提供一个缩写,即 .sync 修饰符

注意:

带有 .sync 修饰符的 v-bind 不能和表达式一起使用 (例如 v-bind:title.sync=”doc.title + ‘!’” 是无效的)。取而代之的是,你只能提供你想要绑定的 property 名,类似 v-model

App.vue






P.vue





C.vue





vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第17张图片

vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第18张图片


3.8 命名注意点

  • 注册组件的时候使用了“驼峰命名”,那么在使用时需要转换成“短横线分隔命名”

例如:注册时:myFather->使用时:my-father

  • 在传递参数的时候如果想使用“驼峰名称”,那么就必须写成“短横线分隔命名”

例如:传递时:parent-name="name"->接收时:props:["parentName"]

  • 在传递方法时不能使用“驼峰命名”,只能使用“短横线分隔命名”

例如:parent-say="say"->this.$emit("parent-say")


四、跨组件传值及多级传递

4.1 跨组件传值--EventBus

兄弟组件之间进行通信

两个没有任何引入关系的组件, 要如何互相通信呢?

什么时候需要 EventBus 技术:

当2个没有引用关系的组件之间需要通信传值

EventBus 技术的本质是什么:

空白 vue 对象,只负责 $on 注册事件 和 $emit 触发事件

$off -- 移除事件

MyProduct.vue 向 List.vue 传值

语法(步骤):

  • 1.src/EventBus/index.js – 创建空白Vue对象并导出

import Vue from 'vue'

// 导出空白的 vue 对象
export default new Vue()
  • 2.在要接收值的组件(List.vue) eventBus.$on('事件名', 函数体)--接收方
  • 3.在要传递值的组件(MyProduct.vue) eventBus.$emit('事件名', 值)--传递方

App.vue,



MyProduct.vue,





List.vue,





vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第19张图片


4.2 数据和方法的多级传递

在Vue中如果儿子想使用爷爷的数据,必须一层一层往下传递

在Vue中如果儿子想使用爷爷的方法,必须一层一层往下传递

vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第20张图片


五、组件插槽--v-slot指令

通过 slot 标签, 让组件内可以接收不同的标签结构显示 

5.1 什么是v-slot指令?

v-slot指令是Vue2.6中用于替代slot属性的一个指令

在Vue2.6之前,我们通过slot属性告诉Vue当前内容填充到哪一个具名插槽

从Vue2.6开始,我们通过v-slot指令告诉Vue当前内容填充到哪一个具名插槽

语法口诀:

组件内用占位

vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第21张图片

 

注意点:

v-slot指令只能用在template标签上,可以使用#替代v-slot

App.vue



UseSlot.vue





Pannel.vue





vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第22张图片

 


 5.2 使用 slot-scope 接收数据

vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第23张图片


 六 、匿名插槽

  1. 默认情况下不能在使用子组件时,给子组件动态的添加内容
  2. 如果想在使用子组件时想给子组件动态的添加内容,就必修使用插槽(slot)
  3. 插槽可以指定默认数据,如果使用者未动态添加数据,就显示默认数据;反之使用使用者动态添加的数据
  4. 插槽是可以指定名称的,默认情况下未指定名称,我们称之为匿名插槽
  5. 有多少个匿名插槽,填充的数据就会被拷贝多少份
  6. 虽然可以指定多个匿名插槽,但是在企业开发中推荐只写一个匿名插槽

vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第24张图片


七 、具名插槽

7.1 初识具名插槽

什么是具名插槽?

默认情况下有多少个匿名插槽,我们填充的数据就会被拷贝多少份,这导致了所有插槽中填充的内容都是一样的,为了解决这个问题,因此可以使用具名插槽

具名插槽的使用:

通过slot的name属性给插槽指定名称以此来进行区分

在使用时可以通过slot="name"方式,指定当前内容用于替换哪一个插槽

vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第25张图片

 

注意点:

如果没有指定要替换哪个插槽中的内容,则不会被替换

slot属性在Ve2.6中已经废弃,Vue2.6之后使用v-slot指令替代slot属性

v-slot: 指令只能用在template标签上,可以使用#替代v-slot:


7.2 示例

App.vue



UseSlot.vue





Pannel.vue





vue基础--组件详解:初识组件、组件动画、父子组件、跨组件传值及多级传递、EventBus、匿名插槽、具名插槽、v-slot指令、作用域插槽、自定义指令_第26张图片

 


八、作用域插槽

使用插槽时, 想使用组件内的变量? 

8.1 初识作用域插槽

什么是作用域插槽?

作用域插槽就是带数据的插槽,就是让父组件填充子组件插槽内容时也能使用子组件的数据

如何使用作用域插槽

在slot中通过v-bind:数据名称="数据名称"方式暴露数据

在父组件中通过