目录
1、组件
组件是抽象的概念,可以理解为一些符合某种规范的类组合在一起就构成了组件。他可以提供某些特定的功能。
2、注册组件
1. 导入需要的 .vue 的组件
语法:
import 组件名 from '组件路径'
// 导入需要的组件
import Header from '@/components/Header/Header.vue'
注意:这里组件路径里的 '@' 代替 /src 目录 ,具体是在vue.config.js配置文件中使用,一般脚手架创建时就会默认配置。
2. 注册组件
语法:
components:{
// '组件名':组件对象
// 组件名相同可简写:
组件,
},
components:{
// 'Left':Left
Left,
},
注意:这里注册组件在components节点下注册。
3、组件的使用
语法:
<组件></组件>
<!-- 3. 以标签形式,使用注册好的组件-->
<Left></Left>
4、全局组件注册
对全局组件进行注册,以下代码均写在main.js
中。
// 导入需要全局注册的组件
import Hello from "./components/Hello.vue";
Vue.component('MyHello',Hello)
注册过后,即可在任意页面直接使用
全局注册的行为必须在根 Vue 实例 (通过
new Vue
) 创建之前发生
4、组件之间的传值
1.父传子
使用自定义属性
1、在子组件里定义props
第一种方法
// 'msg','user'为父传子的值
props: ['msg','user'],
第二种方法
props: {
// 封装一个 id 属性
id: {
// required 是否为必填项
required: true,
// 数据类型
type: Number,
// 默认值
default: 1
}
},
2、使用子组件时,用定义的props绑定父的值(使用v-bind)
<Left :msg="message" :user="userinfo"></Left>
3、父的值放在 data 里面,值名为绑定的名称
data(){
return{
message: 'Hello 2022!',
userinfo: {
name:'shina',
age: 18
}
}
},
注意:在子组件中的props的值只可读,无法操作更改。
2.子传父
使用自定义事件
1、在子组件中调用 this.$emit() 来触发自定义事件
在子组件中:
<template>
<div class="right-container">
<h3>Right 组件</h3>
<p>{{count}}</p>
<button @click="add">+1</button>
</div>
</template>
<script>
export default {
methods:{
add(){
this.count ++
// 把自增的结果,传给父组件
// 修改数据时,通过 $emit 触发自定义事件
this.$emit('numChange',this.count)
},
}
}
</script>
父接收值:
<Right @numChange="getNewCount"></Right>
data(){
return{
// 定义一个值
countFromSan: 0
}
},
methods:{
// 上面组件绑定自定义事件,并提供一个事件处理函数
getNewCount(val){
this.countFromSan = val
}
},
3.兄弟组件共享数据
使用EventBus通讯
创建EventBus.js:
import Vue from "vue";
export default new Vue()
数据发送方:
<template>
<div class="left-container">
<h3>Left 组件(兄弟共享)</h3>
<button @click="send">点击发送</button>
</div>
</template>
<script>
// 1.导入 eventBus.js 模块
import bus from '../components/eventBus'
export default {
data(){
return{
str: '关关雎鸠,在河之洲。窈窕淑女,君子好逑。\n'+
'参差荇菜,左右流之。窈窕淑女,寤寐求之。\n' +
'求之不得,寤寐思服。悠哉悠哉,辗转反侧。\n' +
'参差荇菜,左右采之。窈窕淑女,琴瑟友之。\n' +
'参差荇菜,左右芼之。窈窕淑女,钟鼓乐之。',
}
},
methods:{
send(){
// 将诗句传给 Right
bus.$emit('show',this.str)
}
}
}
</script>
数据接收方:
<template>
<div class="right-container">
<h3>Right 组件(兄弟共享)</h3>
<hr>
<p> 《关雎》 </p>
<p> {{ strNew }} </p>
</div>
</template>
<script>
// 1.导入 eventBus.js 模块
import bus from '../components/eventBus'
export default {
data(){
return{
count: 0,
// 这里从 Left 获得数据
strNew: '',
}
},
// 在 created 生命函数中为 bus 绑定自定义事件
created() {
bus.$on('show',(val) => {
console.log('从 Left 传入了数据!')
this.strNew = val
})
},
}
</script>
效果图:
5、动态组件
1. 什么是动态组件
动态组件指的是 动态切换组件的显示与隐藏 。
2. 如何实现动态组件渲染
vue 提供了一个内置的 <component> 组件, 专门用来实现动态组件的渲染 。
<button @click="comName='Left'">展示 Left</button>
<button @click="comName='Right'">展示 Right</button>
<!-- 1. component 标签是 vue 内置的,作用: 组件的占位符-->
<!-- 2. is 属性的值,表示要渲染的组件的名字-->
<component :is="comName"></component>
3. 使用 keep-alive 保持状态
默认情况下,切换动态组件时 无法保持组件的状态 。此时可以使用 vue 内置的 <keep-alive> 组件保持动态组 件的状态。
<!-- keep-alive 会把内部的组件进行缓存,而不是销毁组件 -->
<keep-alive>
<component :is="comName"></component>
</keep-alive>
4. keep-alive 对应的生命周期函数
当组件 被缓存 时,会自动触发组件的 deactivated 生命周期函数。当组件 被激活 时,会自动触发组件的 activated 生命周期函数。
// 当组件第一次被创建的时候,既会执行 created 生命周期,也会执行 activated 生命周期
// 但是,当组件被激活的时候,只会触发 activated 生命周期,不再触发 created 生命周期。因为组件没有被重新创建
created() {
console.log('Left 组件被创建了!')
},
destroyed() {
console.log('Left 组件被销毁了!')
},
activated() {
console.log('组件被激活了,activated')
},
deactivated() {
console.log('组件被缓存了,deactivated')
},
5. keep-alive 的 include 属性
include 属性用来指定:只有 名称匹配的组件 会被缓存。多个组件名之间使用 英文的逗号 分隔:
<!-- 在使用 keep-alive 的时候,可以通过 include 指定哪些组件需要被缓存; -->
<!-- 或者,通过 exclude 属性指定哪些组件不需要被缓存;但是:不要同时使用 include 和 exclude 这两个属性 -->
<keep-alive include="MyLeft">
<component :is="comName"></component>
</keep-alive>
6、插槽
1. 什么是插槽
插槽 ( Slot )是 vue 为 组件的封装者 提供的能力。允许开发者在封装组件时,把 不确定的 、 希望由用户指定的部分 定义为插槽。可以把插槽认为是组件封装期间,为用户预留的 内容的占位符 。
2. 体验插槽的基础用法
<!-- 声明一个插槽区域 -->
<!--vue 官方规定: 每一个 slot 插槽,都要有一个 name名称-->
<!--如果省略了 slot 的 name 属性,则有一个默认名称叫做 default-->
<slot name="default">这是 default 的默认内容</slot>
<template>
<p>这是在 Left 组件中的 p 标签</p>
</template>
默认情况下,在使用组件的时候,提供的内容都会被填充到名字为 default 的插槽之中
3. 具名插槽
如果在封装组件时 需要预留多个插槽节点 ,则需要为每个 <slot> 插槽指定 具体的 name 名称 。这种 带有具体名称的插槽 叫做“具名插槽”。在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称。
<template #default>
<p>这是在 Left 组件中的 p 标签</p>
</template>
1.如果要把内容填充到指定名称的插槽中,需要使用 v-slot: 这个指令
2.v-slot: 后面要跟上插槽的名字
3.v-slot: 指令不能直接用在元素身上,必须用在 template 标签上
4.template 这个标签,它是一个虚拟的标签,只起到包裹性质的作用,但不会被渲染为任何实质性的 html 元素
5.v-slot: 指令简写形式 #
4. 作用域插槽
在封装组件的过程中,可以为预留的 <slot> 插槽绑定 props 数据,这种 带有 props 数据的 <slot> 叫做“ 作用域插槽 ”。