组件(Component)是 Vue.js
最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
文章目录
概述:组件化开发
就这个图,看看进行,主要就是说Vue的重点之一就在于组件化开发。
一、局部组件
局部组件的使用:生子挂子用子
1-局部组件的创建
- 使用如下的代码进行一个局部组件的创建,
template
定义局部组件的样式。
var App={
data(){
//返回的一定是一个数据对象
return{
}
},
template:'<div>我是入口组件</div>'
}
2-局部组件的挂载
- 使用如下的代码进行局部组件的挂载,用
key:value
键值对,挂载创建的value
局部组件,并在父组件种用key
值进行调用。
new Vue({
el: '#app',
data: {
},
//挂载子组件
components:{
App: App//key:value 挂上App组件
}
})
3-局部组件的调用
- 调用局部组件有两种方式,都是使用闭合标签调用(i)在父组件的
template
种进行使用,(ii)在vue
对象绑定的dom
元素中使用标签进行调用。
<div id="app">
<App></App>
</div>
//父组件直接可以使用,如何使用?使用标签引用
template:'<App></App>'
如果我们此时打印父子组件的关系,那么她会这样显示
二、全局组件
使用如下的代码创建三个全局组件,它们在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。也可以被别的局部组件所使用,即App
局部组件。全局组件自动挂载。
Vue.component("Vcontent" ,{
template:'<div>我是侧边栏组件</div>'
})
Vue.component("Vheader", {
template:'<div>我是头部组件</div>'
})
Vue.component("Vaside", {
template:'<div>我是内容组件</div>'
})
//局部入口组组件的声明
var App={
template: '<div><Vheader/><Vaside/><Vcontent/>我是入口组件</div>',
};
当然无论是全局组件还是局部组件,都是麻雀虽小,五脏俱全,可以作为一个Vue对象进行完善,既可以有data,也可以有method,完善之后再合并在一起,使用vue对象绑定到dom上,然后数据驱动视图------------
1、问题:组件内容无法分发:v-slot
插槽的使用
如下代码要实现的效果是,将子组件Vbtn
在父组件中引用,并显示登陆注册按钮,
Vue.component("Vbtn", {
template:`
<button>按钮</button>
`
})
Vue.component("Parent",{
data(){
return{
msg: "I am the data from the Parent"
}
},
template:`
<div>
<h2>I am the parent.</h2>
<Vbtn>登陆</Vbtn>
<Vbtn>注册</Vbtn>
</div>
`
});
但是我们的运行效果是这样的
可以看到button显示的文字依然是Vbtn的文字,并不是我们调用时显示的文字。这时我们需要用到v-slot
按钮,我们将Vbtn
的定义修改为如下形式
Vue.component("Vbtn", {
template:`
<!--插槽:Vue提供的内置全局组件slot,承载分发内容的出口-->
<button>
<slot>
<!--这里是你分发的内容-->
</slot>
</button>
`
})
这样就好了
2、V-slot
的进阶使用-玩转官方组件
在官方文档中可以找到非常多的button的样式,也有其他组件的样式,我们要如何把他们应用到我们的程序里面呢。(以button为例)
- 有了
v-slot
的基础,我们可以先写出button的名字
Vue.component("Vbtn", {
template:`
<!--插槽:Vue提供的内置全局组件slot,承载分发内容的出口-->
<button>
<slot>
<!--这里是你分发的内容-->
</slot>
</button>
`
})
Vue.component("Parent",{
data(){
return{
msg: "I am the data from the Parent"
}
},
template:`
<div>
<h2>I am the parent.</h2>
<Vbtn>主要按钮</Vbtn>
<Vbtn>成功按钮</Vbtn>
</div>
`
});
- 然后呢,我们给我们的子组件一个
default
的class
,怎么做呢,我们先吧默认按钮的样式复制下来,然后写一个<style/>
,将该样式命名为default
赋予我们的Vbtn
组件。
Vue.component("Vbtn", {
template:`
<!--插槽:Vue提供的内置全局组件slot,承载分发内容的出口-->
<button class="default">
<slot>
<!--这里是你分发的内容-->
</slot>
</button>
`
})
然后呢?我们如何添加其他的样式?我们先按照上面的方法取出两个按钮的样式–
将他们分别定义成css属性,
.success {
color: #fff;
background-color: #67c23a;
border-color: #67c23a;
}
.info {
color: #fff;
background-color: #909399;
border-color: #909399;
}
然后我们如何在父组件中复用时,给子组件不同的class?还记得v-bind
命令吗?捆绑一切属性并动态改变!
- 首先我们在子组件的定义中引入
<button class="default" :class='type'>
,:即v-bind
,捆绑从父组件传来的参数type
,自然的子组件需要prop
命令接受参数props:['type']
。 - 父组件使用
Vbtn
时传入参数type
:<Vbtn type='success'>主要按钮</Vbtn>
即可。
Vue.component("Vbtn", {
template:`
<!--插槽:Vue提供的内置全局组件slot,承载分发内容的出口-->
<button class="default" :class='type'>
<slot>
<!--这里是你分发的内容-->
</slot>
</button>
`,
props:['type']
})
Vue.component("Parent",{
data(){
return{
msg: "I am the data from the Parent"
}
},
template:`
<div>
<h2>I am the parent.</h2>
<Vbtn type='success'>主要按钮</Vbtn>
<Vbtn type='info'>成功按钮</Vbtn>
</div>
`
});
三、组件通信
1、父子之间通信
(1)先给父组件中绑定自定义的属性
使用如下的代码再给Child
子组件绑定父组件的数据msg
,(:
是v-bind
的缩写)
Vue.component("Child",{
template:`
<div>
<h3>I am the child.</h3>
</div>
`
});
Vue.component("Parent",{
data(){
return{
msg: "I am the data from the Parent"
}
},
template:`
<div>
<h2>I am the parent.</h2>
<Child :childData="msg/>
</div>
`
});
(2)在子组件中使用props
接受父组件传递的数据
只需要将全局组件Child
改成如下形式就接受了父组件传来的数据
Vue.component("Child",{
template:`
<div>
<h3>I am the child.</h3>
</div>
`,
props:['childData']
});
(3)尽情操作
比如我们可以使用如下代码,在子组件中将input
的内容与父组件的数据进行双向绑定。但是注意,这里的双向绑定,修改的只是childData
,而不会影响父组件中msg
属性的值。
Vue.component("Child",{
template:`
<div>
<h3>I am the child.</h3>
<input type="textarea" v-model='childData'></input>
</div>
`,
props:['childData']
});
一开始如左图,最后一行是msg
直接输出,倒数第二行是childData
直接输出,我们修改text
文本框的内容会如何?
可以看到只有childData
的内容发生了改变
因此我们只使用v-model
时无法到达目的的,需要新的子-》父通信机制。
2、子父通信
(1). 在父组件中绑定自定义的事件。(这里绑定的是事件而不是属性)
先来分析一下对父组件的操作
Vue.component("Parent",{
data(){
return{
msg: "I am the data from the Parent"
}
},
template:`
<div>
<h2>I am the parent.</h2>
<Child :childData="msg" @childHandle="childHandle"/>
<h2>{{msg}}</h2>
</div>
`,
methods:{
childHandle(){
}
}
});
注意我们这里使用了<Child :childData="msg" @childHandle="childHandle"/>
v-on的对象并不是一个事件,而是我们在methods
中自定义的函数名,他将接受子组件在这里传回来的值。
(2). (重点)在子组件中触发原生事件,在函数中使用$emit
触发父组件中的事件处理函数。
Vue.component("Child",{
template:`
<div>
<h3>I am the child.</h3>
<input type="text" v-model="childData" @input="changeValue(childData)"/>
</div>
`,
props:['childData'],
methods:{
changeValue(val){
//在函数中使用$emit触发父组件的事件,两个参数
//$emit(自定义的事件名,消息)
this.$emit("childHandle", val)
}
}
});
注意这里的一些细节问题,
- 首先
@input="changeValue(childData)"
我们使用v-on
绑定的input
事件传入一个参数,这个参数就是我们想传回父组件的参数。 - 处理事件的函数中,我们将传入的参数使用
$emit
进行操作,这个内置函数的功能有两个,一个是触发我们父组件中的处理函数childHandle
,同时将参数传递给childHandle
。(自定义的事件一定要使用$emit
去触发) - 父组件接受参数,用如下代码,父组件接受到子组件传送来的
val
参数,然后就可以用val
参数进行自身参数的更新。
methods:{
childHandle(val){
console.log(val);
}
}