组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
组件是可复用的 Vue 实例,且带有一个名字:在以下例子中是 。它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项没有。
<div id="components-demo">
<button-counter>button-counter>
div>
(见vue-cli手脚架创建vue项目详细步骤)
import Vue from 'vue'
import App from './App.vue'
// 引入组件路径
import Header from '@/components/Header'
import Footer from '@/components/Footer'
// 全局注册组件 vue.component()
Vue.component('Header',Header)
Vue.component('Footer',Footer)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
创建vue文件,找到项目下的components目录,在这里创建组件,我创建好了Footer.vue,Header.vue
创建好vue文件之后,在app中全局注册,在app.vue中的script标签引入,注册的组件只能在当前app.vue中使用。
script>
import Header from './components/Header.vue'
import Footer from './components/Footer.vue'
export default {
name: 'App',
//局部注册
components: {
Header,
Footer,
},
}
</script>
组件间通信分类可以分成:
1. 父组件传给子组件:
props传递数据:子组件设置props属性,定义接收父组件传递过来的参数
props的两种定义格式:
props:[] //定义为数组,数组中每一项都是变量
props:{} //定义为对象,可以指定数据传递的类型,是否是必须的,指定默认值等等
静态传参:参数名=“参数值”
动态传参:参数名前加冒号,:参数名=“参数值”,
创建Father.vue父组件:
<template>
<div>
<h1>{{msg}}h1>
<hr>
<Child :msg="msgData">Child>
div>
template>
<script>
// 引入子组件
import Child from './Child.vue';
export default{
components:{
Child,
},
data(){
return{
msg:'我是父组件',
msgData:"父组件数据123"
}
}
}
script>
定义子组件Child.vue:props:[] 格式
<template>
<div>
{{msg}}---{{visible}}---{{num}}
</div>
</template>
<script>
export default{
props:["msg","visible","num"],
data(){
return{
}
}
}
</script>
定义子组件Child.vue:props:{} 格式
<template>
<div>
{{msg}}---{{visible}}
<br>
--------
{{num}}-----{{typeof num}}
<br>
--------
{{ages}}
div>
template>
<script>
import { stringify } from 'qs';
export default{
// props:["msg","visible","num"],
props:{
msg:{
type:String,
//必传项
required:true,
// 设置默认值 如果父组件没有传该值,则使用默认值
default(){
return "hello"
}
},
num:Number,
visible:Boolean,
ages:{
type:Array,
//自定义校验器规则
validator(val){
return val>18
}
}
// msg,
// num,
// visible
},
data(){
return{
}
}
}
script>
2. 子组件传给父组件
$emit():由子组件发射事件(自定义事件)
$emit(‘事件名’,‘参数值’)
Father.vue:
<template>
<div>
<h1>{{msg}}</h1>
<hr>
<Child @my-event="handler"></Child>
</div>
</template>
<script>
// 引入子组件
import Child from './Child.vue';
export default{
components:{
Child,
},
data(){
return{
msg:'我是父组件',
msgData:"父组件数据123"
}
},
methods:{
handler(a){
console.log(a);
this.msg=a
}
}
}
</script>
Child.vue:
<template>
<div>
<button @click="toSend">向Father发送数据</button>
</div>
</template>
<script>
export default{
data(){
return{
subMsg:"把123给你"
}
},
methods:{
toSend(){
this.$emit('my-event',this.subMsg)
}
}
}
</script>
兄弟之间通信用EventBus,创建一个事件时间总线,兄弟组件之间通过 e m i t 触发自定义事件, emit触发自定义事件, emit触发自定义事件,emit第二个参数为传递的值,另一个兄弟组件通过$on监听自定义的事件。
这里在src下创建了一个事件总线eventBus.js:
import Vue from 'vue';
export default new Vue()
创建兄弟组件Header.vue和Footer.vue,两者都要引入事件总线
Header.vue:
<template>
<div>
{{msgH}}
<button @click="handler">传值给Footer</button>
</div>
</template>
<script>
//引入事件总线
import Bus from '../eventBus.js'
console.log(Bus,'事件总线');
export default{
data(){
return{
msgH:"头部组件",
Footer:"这是兄弟组件Footer"
}
},
methods:{
handler(){
//兄弟组件传值
// 1.兄弟组件使用$emit 发射事件 携带参数
// console.log(this.Footer);
Bus.$emit('toFoot',this.Footer)
}
}
}
</script>
Footer.vue:
<template>
<div>
{{msgF}}
</div>
</template>
<script>
// 引入事件总线
import Bus from '../eventBus.js'
import FooterChild from './FooterChild.vue'
export default{
components:{
FooterChild
},
data(){
return{
msgF:"底部组件"
}
},
created(){
Bus.$on('toFoot',(a)=>{
console.log(a,'这是Header传给我的值');
})
}
}
</script>
provide和inject:
// 祖先组件使用provide方法提供传递的数据
provide(){
return {
"msg":this.msg,
'a':this.a
}
}
子孙组件:
inject:['msg','a']
上层的数据流向下层。
在父组件给子组件传值的时候,父组件可以改子组件的数据,但是子组件不可以更改父组件的数据。