五、组件通讯 (介绍)
导入 : 演示子组件访问父组件数据,发现报错 【父组件访问子组件数据,也报错】
-
组件是一个独立、封闭的个体
-
也就是说 : 默认情况下,组件中的数据, 只能在组件内部使用,无法直接在组件外部使用
-
可以将 vue 实例看做一个组件
-
-
对于组件之间需要相互使用彼此的情况,应该使用 组件通讯 机制来解决
-
组件通讯的三种情况 :
- 父组件将数据传递给子组件(父 -> 子)
- 子组件将数据传递给父组件 (子 => 父)
- 非父子组件(兄弟组件)
03-组件的通信.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 报错 -->
<div>{{ cmsg }}</div>
<child></child>
</div>
<script src="./vue.js"></script>
<script>
/**/
/**
* 组件是独立 封闭的个体,
组件之间是不能直接访问数据的 , 根据组件之间的通信机制去访问
通信机制
1. 父组件把数据传递给子组件 (父传子)
2. 子组件把数据传递给父组件 (子传父)
3. 非父子之间传递数据 (兄弟级)
*/
// 注册组件
// 子组件
Vue.component('child', {
template: `
// 报错
<div> 子组件 : {{ pmsg }} </div>
`,
data() {
return {
cmsg: '子组件的信息'
}
}
})
// 父组件
const vm = new Vue({
el: '#app',
data: {
pmsg: '父组件的数据'
}
})
</script>
</body>
</html>
六、父 ==> 子 (重点) 两步
- 通过属性, 父组件将要传递的数据,传递给子组件
<child :msg="pmsg"></child>
- 子组件通过 props 配置项,来指定要接收的数据
props: ['msg']
// 以后使用
- 组件内 : msg
- 事件中 : this.msg
完善 TodoMVC => 完成 传值 + 渲染列表页
04-父传子.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<!--
父传子 父组件的数据传递给子组件,
父传子 (两步)
1. 通过属性, 父组件把数据传递给子组件 :msg='pmsg'
2. 子组件通过props配置项, 指定一下要接收过来的数据 props:['msg']
-->
<div id="app">
<!-- 第一步 : 通过属性, 父组件把数据传递给子组件 -->
<child :msg="pmsg"></child>
</div>
<script src="./vue.js"></script>
<script>
// 子组件
Vue.component('child', {
template: `
<div> 子组件 : {{ msg }} </div>
`,
// 第二步 : 子组件通过 props 配置项 指定一下要接收过来的数据
props: ['msg']
})
// 父组件
const vm = new Vue({
el: '#app',
data: {
pmsg: '父组件里的信息'
}
})
</script>
</body>
</html>
七、子 ==> 父 (重点) 三步
- 父组件中定义一个方法
// 【这里的父组件里不用写成bus中的$on,就methods中的一个普通方法。】
pfn(arg) {
console.log('父组件中接受到子组件传递过来的数据:', arg)
}
- 通过
自定义事件
, 父组件将这个方法传递给子组件
// 自定义事件,注意加 @
<child @fn="pfn"></child>
- 子组件调用这个方法( 触发父组件中传递过来的自定义事件 )
// 在钩子函数里演示也可以,自己调用
created() {
// 调用父组件中的方法 pfn
// 注意:通过 $emit 方法来触发事件 fn
// 第一个参数:表示要触发的自定义事件名称,也就是 @fn
// 第二个参数:表示要传递给父组件的数据
this.$emit('fn', 'child msg')
}
完善 TodoMVC => 完成 传值 +添加+ 删除+修改数据+清除完成
05-子传父.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<!--
子传父 子组件把数据传递给父组件
三步骤
1. 父组件准备一个方法 pfn(){}
2. 通过自定义事件, 把方法传递给子组件 @fn='pfn'
3. 子组件通过$emit触发事件,等同于调用了这个方法
this.$emit('fn','子组件里的数据')
-->
<div id="app">
<!-- 第二步 : 通过自定义事件 把方法传递给子组件 -->
<!-- 例子 @click="f" 注意加 @ -->
<child @fn="pfn"></child>
</div>
<script src="./vue.js"></script>
<script>
// 子组件
Vue.component('child', {
template: `
<div> 子组件 : </div>
`,
created() {
// 例子
// @click='f'
// 1. 点击 => 调用f
// 2. 手动触发 this.$emit('click') => f
// 第三步 : 子组件里面触发这个事件,就调用了pfn
// $emit(参数1:事件 参数2:传递的数据)
this.$emit('fn', '我是子组件里的数据')
}
})
const vm = new Vue({
el: '#app',
data: {},
// 第一步: 父组件准备好一个方法
methods: {
// 【这里的父组件里不用写bus中的$on那样,就methods中的一个普通方法。】
pfn(res) {
console.log('pfn调用了:', res) // pfn调用了: 我是子组件里的数据
}
}
})
</script>
</body>
</html>
补充的案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<one @c-fn="pFn"></one>
</div>
<script src="./vue.js"></script>
<!-- <script src="./node_modules/vuex/dist/vuex.js"></script> -->
<script>
Vue.component('one', {
template: `<div><button @click="btnClick">按钮</button></div>`,
methods: {
btnClick() {
console.log(111)
this.$emit('c-fn', 222)
}
},
created() {
// this.$emit('c-fn', 333)
},
})
const vm = new Vue({
el: '#app',
data: {
msg: ''
},
methods: {
pFn(param) {
console.log('父组件', param)
}
}
})
</script>
</body>
</html>