组件通讯
父子组件的通讯
父组件通过props向子组件传递数据
写法一:
写法二:
<div id="app">
// 在使用组件的时候绑定
// 不支持驼峰命名 cMovies要写成c-movies
<cpm :c-movies="movies" :c-message="message"></cpn>
</div>
<template id="cpn">
<div>
<li v-for="item in cMovies">{{item}}</li>
<h2>{{cMessage}}</h2>
</div>
</template>
const cpn = {
template: '#cpn',
// 把数组里的当变量来看了
props: {
// 类型限制
// cMovies: Array,
// cMeesage: String,
// 类型限制 + 提供一些默认值 or required表示必传值,不然报错
cMessage: {
type: String,
default: '哈',
required: true
},
cMovies: {
type: Array, // 对象or数组类型的时候, 默认值必须是个函数
default() {
return {}
}
}
}
data () {
return {}
}
}
const app = new Vue({
el: '#app',
data: {
meassage: '哈哈哈',
movies: ['哈喽', '嗨', '哟哟']
},
components: {
cpn
}
})
子组件通过事件向父组件发送数据
// 父组件模板
<div id="app">
// 2.父组件监听一个事件
// 不能写驼峰
<cpm @itemclick="cpnClick"></cpn>
</div>
// 子组件模板
<template id="cpn">
<div>
<button v-for="item in categories"
@click="btnClick(item)">
{{item.name}}
</button>
</div>
</template>
// 子组件
const cpn = {
template: '#cpn',
data() {
return {
categories: [
{id: 'aaaa', name: '热门推荐'},
{id: 'bbbb', name: '手机数码'},
{id: 'cccc', name: '家用家电'},
{id: 'dddd', name: '电脑办公'},
]
}
},
methods: {
btnClick(item) {
// 要把item传给父组件
// 1. 发送一个事件 (自定义事件)
// 会把item当成默认的传到父组件去
this.$emit('itemclick', item)
]
}
}
// 父组件
const app = new Vue({
el: '#app',
data: {
meassage: '哈哈哈'
},
components: {
cpn
},
methods: {
// 3. 父组件监听的事件
cpnClick(item) {
console.log('成功了', item);
}
}
})
父子组件通讯-双向绑定
- $children: 拿所有子组件
- $refs: 拿指定的子组件
// this.$children是一个数组类型, 它包含所有子组件对象
// 通过遍历, 取出所有子组件的message状态
<div id="app">
<cpm></cpn>
<cpm></cpn>
// 使用$refs的时候, 在想要访问的子组件上添加ref属性
<cpm ref="aaa"></cpn>
<buttun @click="btnClick">按钮</button>
</div>
<template id="cpn">
<div>
我是子组件
</div>
</template>
const app = new Vue({
el: '#app',
data: {
meassage: '哈哈哈'
},
methods: {
btnClick() {
cosole.log(this.$children);
// $children 的使用方法, 一般用的少, 下标不固定
// this.$children[0].showMessage();
// this.$children[0].name;
//for (let c of this.$children) {
// console.log(c.name); // 我是子组件的name
// c.showMessage(); // showMessage
//}
// $refs 的使用方法 => 对象类型, 默认是一个空的对象
console.log(this.$refs.aaa.name); // 我是子组件的name
}
}
components: {
cpn: {
template: "#cpn",
data() {
return {
name: '我是子组件的name'
}
},
methods: {
showMessage() {
cosole.log('showMessage');
}
}
}
}
})
子组件访问父组件
- $parent: 上一级父组件
- $root: 根组件
<div id="app">
<cpm></cpn>
</div>
<template id="cpn">
<div>
<ccpn></ccpn>
</div>
</template>
<template id="ccpn">
<div>
<h2>我是子组件</h2>
<button @click="btnClick">按钮</button>
</div>
</template>
const app = new Vue({
el: '#app',
data: {
meassage: '哈哈哈'
},
components: {
cpn: {
template: "#cpn",
data() {
return {
name: '我是cpn的name'
}
},
conmponents: {
ccpn: {
template: '#ccpn',
btnClick() {
// 1. 访问父组件$parent
// 不建议这么写, 一层套一层 复用性太差
console.log(this.$parent);
console.log(this.$parent.name); // 我是cpn的name
// 2. 访问根组件 $root
console.log(this.$root.meassage); // 哈哈哈
}
}
}
}
}
})
插槽slot:
作用:
组件的插槽是为了让我们封装的组件更加具有扩展性
让使用者可以决定组件内部的一些内容到底展示什
基本使用
- 插槽的基本使用
- 插槽的默认值 button
- 如果有多个值同时放入到组件进行替换时, 一起作为替换元素
<div id="app">
// 使用默认值替换
<cpm></cpn>
// 插槽替换的元素
<cpm><span>这是替换的内容呀</span></cpn>
// 多个元素
<cpm>
<div>第一个元素</div>
<p>第二个元素</p>
</cpn>
</div>
<template id="cpn">
<div>
<div>这个是标题</div>
<p>这个是内容</p>
// 放入插槽
<slot>默认值元素</slot>
</div>
</template>
const app = new Vue({
el: '#app',
data: {
meassage: '哈哈哈'
},
components: {
cpn: {
template: '#cpn'
}
}
})
具名插槽:
<slot name='aa'></slot> 使用name属性给插槽命名
使用 <template v-slot:aa></template> 标签和v-slot指令来使用
<div id="app">
<cpm></cpn>
<cpm><button slot="left">返回</button></cpn>
<cpm><span slot="center">中间标题</span></cpn>
</div>
<template id="cpn">
<div>
<slot name="left"><span>左边</span></slot>
<slot name="center"><span>中间</span></slot>
<slot name="right"><span>右边</span></slot>
</div>
</template>
const app = new Vue({
el: '#app',
data: {
meassage: '哈哈哈'
},
components: {
cpn: {
template: '#cpn'
}
}
})
作用域插槽:父组件模板所有的东西都在父级作用域内编译, 子组件模板的所有东西会在子级作用域内编译!
<div id="app">
<cpm v-show="isShow">我是一</cpn> // true
</div>
<template id="cpn">
<div>
<p v-show="isShow">我是二</p> // false
</div>
</template>
const app = new Vue({
el: '#app',
data: {
isShow: true // Vue实例中的属性
},
components: {
cpn: {
template: '#cpn',
data() {
return {
isShow: false // 子组件中的属性
}
}
}
}
})
作用域插槽使用:
父组件替换插槽的标签, 但是内容由子组件来提供
<div id="app">
<cpm></cpn>
<cpm>
// 2. 获取子组件中的num
<template slot-scope="slot">
// 根据之前的起名来取 如 slot.aaa
<span v-for="item in slot.data">{{item}}</span>
</template>
</cpn>
<cpm></cpn>
</div>
<template id="cpn">
<div>
// 1. slot定义 'data'可以随便起名 如 :aaa="num"
<slot :data="num">
<ul>
<li v-for="item in num">{{item}}</li>
</ul>
</slot>
</div>
</template>
const app = new Vue({
el: '#app',
data: {
message: '哈哈哈'
},
components: {
cpn: {
template: '#cpn',
data() {
return {
num: ['1', '2', '3', '4', '5']
}
}
}
}
})
喜欢的小伙伴点个赞吧,关注博主受益多多 !!!
下篇vuex