提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
深入了解六种vue组件组件间通信
提示:以下是本篇文章正文内容,下面案例可供参考
一、自定义事件
原生DOM—button可以绑定系统事件—click点击事件等等
非原生DOM节点不能绑定系统事件 (不起作用:因为属于自定义事件)需要添加native修饰符@click.native 可以把自定义事件改为原生DOM事件
// 父组件
<template>
<div>
<Event2 @click="handler2" ></Event2>
</div>
</template>
methods: {
handler2(params){
console.log(params);
}
}
// 子组件
<template>
<div >
<h2>Event2组件</h2>
<button @click="$emit('click',66666)">分发自定义click事件</button>
</div>
</template>
二、v-model实现父子组件之间的通信
v-model本质上是一个语法糖 实现原理是v-on绑定msg 然后再通过@input事件修改msg的值
<!--父组件-->
<template>
<div>
<h2>深入v-model</h2>
<input type="text" v-model="msg">
<span>{{msg}}</span>
<br>
<h2>深入v-model原理</h2>
<!-- 原生DOM当中是有oninput事件:当表单元素发生文本的变化的时候就会立即出发 -->
<input type="text" :value="msg" @input=" msg = $event.target.value"/>
<span>{{msg}}</span>
<!--并非原生DOM:自定义组件-->
<!-- <CustomInput :value="msg" @input="msg = $event"></CustomInput>
<CustomInput v-model="msg"></CustomInput> -->
<CustomInput :value="msg" @input="msg = $event"/>
<hr>
</div>
</template>
export default {
name: 'ModelTest',
data() {
return {
msg:"我爱塞北的大雪呀"
}
},
components: {
CustomInput
}
}
//子组件
<template>
<div style="background: #ccc; height: 50px;">
<h2>input包装组件----{{value}}</h2>
<input :value="value" @input="$emit('input',$event.target.value)"/>
</div>
</template>
sync实现父子组件通信 和v-model类似 可以实现父子组件数据同步
代码如下(示例):
父组件
<template>
<div>
小明的爸爸现在有{{ money }}元
<h2>不使用sync修改符</h2>
// @upadata:money="money=$event"属于自定义事件
<Child :money="money" @update:money="money = $event"></Child>
<h2>使用sync修改符</h2>
<!-- -->
<Child :money.sync="money"></Child>
<h2>使用v-model修改符</h2>
<hr />
</div>
</template>
<script type="text/ecmascript-6">
import Child from './Child.vue'
import Child2 from './Child2.vue'
export default {
name: 'SyncTest',
data() {
return {
money: 10000
}
},
components: {
Child,
Child2
}
}
</script>
// 子组件Child
<template>
<div style="background: #ccc; height: 50px;">
<span>小明每次花100元</span>
<button @click="$emit('update:money',money - 100)">花钱</button>
爸爸还剩 {{money}} 元
</div>
</template>
<script type="text/ecmascript-6">
export default {
name: 'Child',
props:['money']
}
</script>
// 子组件Child2
<template>
<div style="background: #ccc; height: 50px;">
<span>小明每次花100元</span>
<button>花钱</button>
爸爸还剩 ??? 元
</div>
</template>
<script type="text/ecmascript-6">
export default {
name: 'Child2'
}
</script>
a t t r s 与 attrs与 attrs与listeners`实现组件间通信
// 父组件
<template>
<div>
<h2>自定义带Hover提示的按钮</h2>
<!-- 二次封装的HintButton按钮的时候,把人家el-button需要的数据传递过去 -->
<HintButton type="success" icon="el-icon-plus" title="我是中国人" @click="handler"/>
</div>
</template>
<script type="text/ecmascript-6">
import HintButton from './HintButton';
export default {
name: 'AttrsListenersTest',
components:{
HintButton
},
methods: {
handler() {
alert('666');
},
},
}
</script>
// 子组件
<template>
<div>
<a :title="title">
<!-- v-bind不能写成:v-on也不能写成@ -->
<el-button v-bind="$attrs" v-on="$listeners">添加</el-button>
</a>
</div>
</template>
<script>
export default {
name: "",
props:['title'],
mounted(){
//this.$listeners 他也是组件组件实例自身的一个属性 它可以接收到父组件给子组件传输的自定义事件
//this.$attrs:可以获取到父亲传递的数据【props】
//this.$attrs是可以获取父亲传递的props数据,如果子组件通过
//props:[],接受,this.$attrs属性是获取不到的
console.log(this.$attrs);
console.log(this.$listeners);
}
};
</script>
<style scoped></style>
c h i l d r e n 和 children和 children和parent
可以通过组件实例ref来传递数据
也可容易通过
c
h
i
l
d
r
e
n
和
children和
children和parent组件实例来传递数据
// 父组件
<template>
<div>
<h2>BABA有存款: {{ money }}</h2>
<button @click="JieQianFromXM(100)">找小明借钱100</button><br />
<button @click="JieQianFromXH(150)">找小红借钱150</button><br />
<button @click="JieQianAll(200)">找所有孩子借钱200</button><br />
<button @click="SendInfo">我是baba</button>
<br />
<!-- 小明 -->
<Son ref="xm" />
<br />
<!-- 小红 -->
<Daughter ref="xh"/>
</div>
</template>
<script>
import Son from "./Son";
import Daughter from "./Daughter";
export default {
name: "ChildrenParentTest",
data() {
return {
money: 1000,
};
},
methods: {
//找儿子借钱
JieQianFromXM(money) {
//父组件的数据累加100
this.money += money;
this.$refs.xm.money -= money;
},
JieQianFromXH(money) {
//父组件的数据累加150
this.money += money;
this.$refs.xh.money -= money;
},
JieQianAll(money){
this.money += 2*money;
this.$children.forEach(item=>item.money-=money);
//不建议用枚举获取子组件:因为没办法确定到底是那个子组件
// this.$children[0].money -=money;
},
SendInfo(){
//在父组件中获取到子组件(数据+方法)
this.$refs.xm.tinghua();
}
},
components: {
Son,
Daughter,
},
};
</script>
<style></style>
// 子组件
<template>
<div style="background: #ccc; height: 50px;">
<h3>儿子小明: 有存款: {{money}}</h3>
<button @click="geiQian(50)">给BABA钱: 50</button>
</div>
</template>
<script>
export default {
name: 'Son',
data () {
return {
money: 30000
}
},
methods: {
tinghua(){
console.log('我是小明,我听爸爸的话');
},
geiQian(money){
this.money-=money;
this.$parent.money+=money;
}
}
}
</script>
作用域插槽
// 父组件
<template>
<div>
<h2>效果一: 显示TODO列表时, 已完成的TODO为绿色</h2>
<List :todos="todos">
<!-- 书写template -->
<template slot-scope="todo">
<h5 :style="{color:todo.todo.isComplete?'green':'black'}">{{todo.todo.text}}</h5>
</template>
</List>
<List :todos="todos">
<!-- 书写template -->
<template slot-scope="todo">
<a :style="{color:todo.todo.isComplete?'green':'black'}">{{todo.todo.text}}</a>
</template>
</List>
<hr>
<h2>效果二: 显示TODO列表时, 带序号, TODO的颜色为蓝绿搭配</h2>
<List1 :data="todos">
<template slot-scope="{row,index}">
<h1 :style="{color:row.isComplete?'green':'hotpink'}">索引值{{index}}---------{{row.text}}</h1>
</template>
</List1>
</div>
</template>
<script type="text/ecmascript-6">
//子组件
import List from './List'
import List1 from './List1'
export default {
name: 'ScopeSlotTest',
data () {
return {
todos: [
{id: 1, text: 'AAA', isComplete: false},
{id: 2, text: 'BBB', isComplete: true},
{id: 3, text: 'CCC', isComplete: false},
{id: 4, text: 'DDD', isComplete: false},
]
}
},
components: {
List,
List1
}
}
</script>
// 子组件
<template>
<ul>
<li v-for="(todo,index) in data" :key="index">
<!-- 坑:熊孩子挖到坑,父亲填坑 -->
<!-- 数据来源于父亲:但是子组件决定不了结构与外网-->
<slot :row="todo" :index="index "></slot>
</li>
</ul>
</template>
<script>
export default {
name: 'List1',
props: {
data: Array
}
}
</script>