目录
什么是组件 只要是.vue后缀的文件都是一个组件
而组件之间是独立的,相互之间没有关系
当在使用组件的时候,根据彼此嵌套的关系就分为了 父子、兄弟关系
组件都是放在components文件夹中
组件的使用
<div class="box">
<!--以标签的形式使用注册好的组件 -->
<Component></Component>
</div>
//1.导入需要用到的组件
import Component from '@/components/Component.vue'
components: {
Component
}
注册全局组件
在项目中的main.js中,通过Vue.component()方法,进行全局注册
//导入需要全局注册的组件
import Component from '@/components/Component.vue'
// 参数1:字符串格式,表示组件的“注册名称”
// 参数2:需要被全局注册的那个组件
Vue.component('MyComponent',Component )
props组件
用于在父组件中向子组件传递数据
props 是自定义属性,允许使用者通过自定义属性,为当前组件指定初始值
自定义属性的名字,是封装者自定义的 (只要名称合法即可)
props 中的数据,可以直接在模板结构中被使用
props是只读的,不能直接去修改它的值,否则报错
修改props的值就要把值转存到data中
// 父组件 Parent.vue
<template>
<div class="child-container">
<h3>Parent组件</h3>
<hr />
<!--引入了Count并给了初始值 5 如果没给则会用default初始的值-->
<MyCount :message="message" :count="5"></MyCount>
</div>
</template>
//引入子组件
import MyCount from '...'
export default{
data() {
return{
count: 0,
message: '你好啊!我的孩子。'
}
},
components:{
MyCount
}
}
// 子组件
<div>
<h3>MyCount组件</h3>
<p>message的值是:{{message}}</p>
<p>count的值是:{{count}}</p>
<button @click="count++">点击+1</button>
</div>
export default{
props:{
//自定义属性a:{配置选项}
count:{
//定义初始值
default: 0,
//定义传值类型
type: Number,
//定义这是必填项,否则报错
required: true
},
//定义message只能是String
message: String
},
data() {
return{
count: this.init,
}
}
}
上面父组件 通过 :message="message" 和:count="5" 的方式将这两个数据作为Props传递给子组件MyCount,子组件通过poros 选项声明需要接收的Props,既 message 和 count
组件之间样式冲突问题
默认情况下,写在 .vue 组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题
导致组件之间样式冲突的根本原因是:
单页面应用程序中,所有组件的 DOM 结构,都是基于唯一的 index.html 页面进行呈现
每个组件中的样式,都会影响整个 index.html 页面中的 DOM 元素
当使用第三方组件库的时候,如果有修改的第三方组件默认样式的需求,需要用到 /deep/
用法:
/deep/ h5{}
父-子关系传递
父组件向子组件共享数据使用 自定义属性
<!-- Parent.vue 父组件 -->
<template>
<div class="parent-container">
<!-- @customEvent 来自 ChildA 传递的数据-->
<ChildA :msg="message" @customEvent="handleCustomEvent"></ChildA>
<ChildB v-model="dataFromChildB"></ChildB>
</div>
</template>
//导入子组件ChildA和B
import ...A
import ...B
export default{
components:{
ChildA,
ChildB
},
data(){
return{
message: 'hello vue',
dataFromChildB: ''
}
},
methods:{
handleCustomEvent(payload){
//处理来自ChildA的事件
log(payload)
}
}
}
子-父关系传递
子组件向父组件共享数据使用 自定义事件
使用$emit进行传值
<!-- ChildA.vue 子组件 -->
<template>
<div class="parent-container">
<h3>子组件ChildA</h3>
<p>{{message}}</p>
<button @click="emitEvent">Emit Event</button>
</div>
</template>
exprot default{
props:['message'],
methods:{
emitEvent(){
//this.$emit('自定义事件名',要传的值)
this.$emit('customEvent','这是来自ChildA的消息')
}
}
}
上面是父组件通过 props 将 message 传递给 childA子组件,并通过事件 customEvent 监听ChildA的按钮点击事件。
<!-- ChildB.vue 子组件 -->
<template>
<div class="parent-container">
<h3>子组件ChildB</h3>
<input v-model="inputData" />
</div>
</template>
exprot default{
props:['value'],
data(){
reurn{
inputData: ''
}
},
watch:{
inputData(newVal){
this.$emit('input',newVal);
}
}
mounted(){
//接收父组件的初始值
this.inputData = this.Value
}
}
ChildB通过v-modle 接收父组件传递的值,并在输入框中修改后通过 $emit('input',newVal)将新值发送给父组件。
兄弟之间的传递
方案是EventBus 事件总线
EventBus的使用步骤
创建eventBusjs 模块,并向外共享一个 Vue 的实例对象
在数据发送方,调用 bus.$emit(事件名称,要发送的数据)方法触发自定义事件
在数据接收方,调用 bus.$on(事件名称,事件处理函数)方法注册一个自定义事件
//EventBus.js
//创建eventBusjs 模块,并向外共享一个 Vue 的实例对象
import Vue from 'vue'
export default new Vue();
//ChildA
//在数据发送方,调用 bus.$emit(事件名称,要发送的数据)方法触发自定义事件
import bus from '@/EventBus'
export default{
methods:{
sendData(){
bus.$emit('customEvent' '数据来自ChildA')
}
}
}
//ChildB
//在数据接收方,调用 bus.$on(事件名称,事件处理函数)方法注册一个自定义事件
import bus from '@/EventBus'
export default{
mounted:{
bus.$on('customEvent' payload => {
//处理来自ChildA的事件
console,log(payload)
})
}
}
ref引用
用于在组件中获取对DOM元素或子组件的引用
通过 ref 可以在组件内部访问和操作所引用的元素或组件
//1、获取DOM元素的引用
//使用 ref属性 设置一个唯一的名称 然后通过 this.$refs.myButton获取Dom元素
<button ref="myButton"> ref 获取</button >
export default{
mounted(){
count button = this.$refs.myButton
//进行操作
}
}
//2、获取子组件的引用
<ChildA ref="myChild"></ChildA>
export default{
components:{
Child
},
mounted(){
count myChild = this.$refs.myChild
//调用子组件的方法或访问子组件的属性
}
}
需要注意的是, ref 属性可以用在普通HTML元素上,也可以用在组件上。
但是在父组件使用ref获取子组件的引用时,子组件必须通过 components 选项进行注册
在 mounted 生命周期钩子中使用 this.$refs 访问 ref 引用是因为此时的子组件已经被挂载,在其它生命周期或方法中使用时,需要确保子组件挂载完成,然后才能访问