1.概述
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用is特性进行了扩展的原生 HTML 元素。组件注册的时候需要为该组件指定各种参数。
2.组件定义
因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。
一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝
// 1.组件的定义
let component1={
//data选项必须是一个函数
data(){
return{
msg:'我是子组件1'
}
},
//模板
template:`
<div>
<h3>{{msg}}</h3>
<button @click="msg='新数据'">修改数据</button>
</div>
`
}
3.组件注册
要想进行组件使用,先进行组件注册
1. 全局注册
可以使用Vue.component(tagName, options) 注册一个全局组件, 注册之后可以用在任何新创建的 Vue 根实例的模板中。
Vue.component('my-com1',component1)
2. 局部注册
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。局部注册的组件只能在当前组件中使用。
let vm=new Vue({ el:'#app', data:{}, methods:{}, created(){}, //局部注册 components:{ 'my-com2':component2 } })
###完整代码例子:
<body>
<div id="app">
<my-com1></my-com1>
<my-com2></my-com2>
</div>
<script>
// 1.组件的定义
let component1={
data(){
return{
msg:'我是子组件1'
}
},
template:`
<div>
<h3>{{msg}}</h3>
<button @click="msg='新数据'">修改数据</button>
</div>
`
}
let component2={
data(){
return{
msg:'我是子组件2'
}
},
template:`
<div>
<h3>{{msg}}</h3>
<my-com1></my-com1>
</div>
`
}
// 2.组件注册
// 2.1全局注册
Vue.component('my-com1',component1)
let vm=new Vue({
el:'#app',
data:{},
methods:{},
created(){},
// 2.2局部注册
components:{
'my-com2':component2
}
})
</script>
</body>
###效果如下:
4.组件交互/通信
组件 A 在它的模板中使用了组件 B。它们之间必然需要相互通信:
父组件可能要给子组件下发数据,子组件则可能要将它内部发生的事情告知父组件。
在 Vue 中,父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息。
1.子组件内使用父组件数据
1.父组件传递数据给子组件 (可以传递静态属性 动态属性 )
<my-com title='' :msg='msg' attr-a=''>
2.子组件接收并处理数据
{
props:['title','msg','attrA],
template:``
}
2.父组件内使用子组件的数据
事件发射 自定义事件
在子组件内发射 在父组件内接受
子组件发射时机
1.手动按钮发送
2.监听子组件内数据变化,然后发射
在子组件内监听comMsg的变化,this.$emit('',this.comMsg)
父组件的事件处理程序调用,可以更改父组件数据模型中的数据,同步反映到父组件视图中
4.1 父组件传递数据给子组件
<body>
<div id="app">
<!-- 3.组件使用 -->
<button @click="attr2.username='tom'">修改父组件数据值</button>
<my-com :num='1' :attr1="attr1" :parent-data='attr2'></my-com>
<!-- <my-com :num='1' attr1="hello"></my-com> -->
</div>
<script>
// 1.组件的定义
let component1={
// props:['num','attr1','parentData']
props:{
num:[Number,String],
attr1:{
type:String,
required:true,
default:'默认值',
validator(value){
return value.length>=3
}
},
parentData:{
type:Object,
default(){
return{
username:'李四',
age:24
}
}
}
},
data(){
return{
msg:'子组件1'
}
},
template:`
<div>
<h3>{{msg}}</h3>
<h2>父组件传递过来的数据:{{attr1}}-{{parentData}}</h2>
<h4>{{num}}-{{typeof num}}</h4>
</div>
`
}
let vm=new Vue({
el:'#app',
data:{
attr1:'我是父组件数据',
attr2:{
username:'zs',
age:22
},
},
methods:{},
// 2.局部组件注册
components:{
'my-com':component1
}
})
</script>
</body>
4.2 子组件向父组件传递数据
<body>
<div id="app">
<h2>父组件</h2>
<div class="box">
{{parentData}}
</div>
<!-- 父组件 -->
<my-com v-on:child-event="parentHandler">
成功按钮
</my-com>
</div>
<script>
// 1.组件定义
let component1={
data(){
return{
childData:'windows 11'
}
},
methods:{
toEmitHandler(){
// $emit方法可以向上发送数据,并且可以携带数据
// 子组件
this.$emit('child-event',this.childData)
}
},
template:`
<div>
<h3>子组件</h3>
<button @click='toEmitHandler'>发送事件</button>
<button>
<slot></slot>
</button>
</div>
`
}
let vm=new Vue({
el:'#app',
data:{
parentData:'Windows98'
},
methods:{
parentHandler(data){
console.log('我知道了',data);
//修改父组件数据,由父组件自己来决定
this.parentData=data;
}
},
// 2.局部组件注册
components:{
'my-com':component1
}
})
</script>
</body>