-
Vue 53 >> 61(父子组件) [^使用 Vue 父子组件]:
Vue 父子组件
P53 组件的基本使用
创建组件构造对象
const cpnC = Vue.extend({
template: `
<div>
<h2>Vue组件化的基本使用</h2>
</div>
`
})
注册组件
Vue.component('my-cpn',cpnC)
组件的使用
<div id="app">
<my-cpn>
</div>
高复用性,组件可以在多个项目中使用
P53全局组件和局部组件
全局组件: Vue.extend 注册的组件都为全局组件
局部组件:
const app = new Vue({
el: '#app',
data: {
},
components: {
cpn: cpnC
},
在相应的 Vue 实例对象中注册组件,该组件则只对该实例对象起作用
P54父组件和子组件的区别
const cpnC1 = Vue.extend({
template: `
<div>
<h2>注册内容一</h2>
</div>
`
})
注册两个组件
const cpnC1 = Vue.extend({
template: `
<div>
<h2>注册内容一</h2>
</div>
`
})
const cpnC2 = Vue.extend({
template: `
<div>
<h2>注册内容二</h2>
<cpn1></cpn1>
</div>
`,
components: {
cpn1: cpnC1
}
})
在组件二中注册子组件一
const app = new Vue({
el: '#app',
data: {
},
components: {
cpn2: cpnC2
}
})
在 Vue 实例对象中注册父组件cpn2,显示效果如下
![> [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4SRNtdh4-1627034790086)(C:\Users\隔壁的小吴同学\AppData\Roaming\Typora\typora-user-images\image-20210723090701982.png)]](https://img-blog.csdnimg.cn/77981ed0bd2b47c78eb9dca0ebb81ac4.png)
P56 注册组件的语法糖写法
Vue.components ('cpn1',{
template:
`
<div>
<h2>注册内容</h2>
<cpn1></cpn1>
</div>
`
})
全局组件注册的语法糖
const app = new Vue({
el: '#app',
data: {
},
components: {
'cpn2': {
template:
`
<div>
<h2>注册内容</h2>
<cpn1></cpn1>
</div>
`
}
}
})
局部组件的语法糖
P57组件模板的抽离写法
Vue.component('cpn',{
template: '#cpn'
})
1.使用 script 注册
<script type="text/x-template" id="cpn">
<div>
<h2>组件注册</h2>
</div>
</script>
2.使用 template 注册
<template id="cpn">
<div>
<h2>template 组件注册</h2>
</div>
</template>
P58 组件的数据存放_为什么要使用函数返回值
获取 title 注册值:
<template id="cpn">
<div>
<h2>{{title}}</h2>
<h2>template 组件注册</h2>
</div>
</template>
注册组件并尝试获得 title 属性
const app = new Vue({
el: '#app',
data: {
title: '标题'
},
})
不能在实例化 Vue 对象中注册
Vue.component('cpn',{
template: '#cpn',
data() {
return {
title: '标题_component'
}
}
})
而应在注册构造器中返回注册值
为什么使用函数返回:
将一个计数器封装为组件,测试值
Vue.component('cpn',{
template: '#cpn',
data() {
// 三个组件的 data 不是一个 data 对象,函数每次使用都会重新创建
return{
counter: 0
}
},
methods: {
increment() {
this.counter++
},
decrement() {
this.counter--
}
},
})
创建组件并在 data 中 return 值,使用函数返回值每次都会新建函数,避免组件之间影响:
![> [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jyu0NT5j-1627034790088)(C:\Users\隔壁的小吴同学\AppData\Roaming\Typora\typora-user-images\image-20210723110358907.png)]](https://img-blog.csdnimg.cn/cdc66ef7fa4b42828446b068babb55cb.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L01yX2Fzd2w=,size_16,color_FFFFFF,t_70)
// 使其相互影响的
const obj = {
counter: 0
}
当返回是同一个对象时,组件相互影响:
![> [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-avQyDMMK-1627034790089)(C:\Users\隔壁的小吴同学\AppData\Roaming\Typora\typora-user-images\image-20210723110317738.png)]](https://img-blog.csdnimg.cn/38f796ea5e9441b68ab4efcebbcbca52.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L01yX2Fzd2w=,size_16,color_FFFFFF,t_70)
Vue.component('cpn',{
template: '#cpn',
data() {
// 使用函数每次都返回一个新的对象,就没有相互影响
return obj//影响
},
methods: {
increment() {
this.counter++
},
decrement() {
this.counter--
}
},
})
函数返回值的方式可以避免因返回相同对象二影响值的情况
P59 父子组件的通信

父组件向子组件传值的方式 Props:
父组件展示:
<div id="app">
<cpn :cmovies="moveies" :cmessage="message"></cpn>
</div>
注册子组件:
<template id="cpn">
<div>
<h2>{{cmessage}}</h2>
<ul>
<li v-for="item in cmoveies">{{item}}</li>
</ul>
</div>
</template>
注册父组件(Vue实例化组件同等与组件性质)
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
moveies: ['山贼王', '水影忍者', '金魂']
},
components: {
cpn,//增强写法 == cpn: cpn
}
})
将父组件的 message 和 moveies 传递给子组件
1.数组传递
const cpn = {
template: '#cpn',
props: ['cmoveies', 'cmessage'],//数组方式
}
2.对象传递: 默认值 default 以及必传值 required
const cpn = {
template: '#cpn',
props: {
// 类型限制:
// cmovies: Array,
// cmessage: String,
//对象写法:
//对象写法
cmessage: {
type: String,
default: '默认值',
required: true,//必传,不传会报错
},
//类型是对象Array或数组时,默认值必须是一个函数
cmovies: {
type: Array,
default() {
return []
}
}
自定义类型限制示例:
// 自定义类型
// fuction Person (firstName,lastName){
// this.firstName = firstName
// this.lastName = lastName
// }
P61 子组件向父组件传值的方式 Emit:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ash5Qrhi-1627034790093)(C:\Users\隔壁的小吴同学\AppData\Roaming\Typora\typora-user-images\image-20210723171222131.png)]](https://img-blog.csdnimg.cn/4097bd3870a24207b8334b4c5f6386f3.png)
//父组件
<div id="app">
<cpn @itemclick="cpClick"></cpn>
</div>
//子组件
<template id="cpn">
<div>
<button v-for="item in categories"
@click="btnClick(item)">
{{item.name}}
</button>
</div>
</template>
const app = new Vue({
el: '#app',
data: {
},
components:{
cpn
},
methods: {
cpnClick(item) {
console.log('cpnClick',item);
}
}
})
注册父组件
const cpn = {
template: '#cpn',
data() {
return {
categories: [
{id:'a',name:'内容a'},
{id:'b',name:'内容b'},
{id:'c',name:'内容c'},
{id:'d',name:'内容d'},
]
}
},
methods: {
btnClick(item) {
this.$emit('itemclick', item);
}
},
}
注册子组件:
自定义事件,$emit 发送一个事件,
父组件将方法的引用传递给子组件,其中,cpnClick 是父组件中methods 中定义的方法名称,itemclick 是子组件调用传递过来方法时候的方法名称。
<cpn @itemclick="cpnClick"></cpn>//@itemclick == v-on:itemclick
``
|