Vue3父子组件间通信和组件间双向绑定怎么实现
本篇内容主要讲解“Vue3父子组件间通信和组件间双向绑定怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue3父子组件间通信和组件间双向绑定怎么实现”吧!
假如确要修改,可以使用下面说的方式进行通信:
首先,在子组件的UI点击回调方法中,调用
,this.$emit('【自己设置事件名】')
向外发送一个
;事件
接着各级父组件会收到这个事件,
则在父组件中 调用 子组件标签处,
以
的形式,@【事件名】= "回调方法名"
该事件以及配置监听
;回调方法
中就可 对 子组件用意修改 的 父组件数据字段 进行修改;回调方法
注意,
触发事件的命名,用(如下heHeDa);驼峰命名法
监听事件的命名,用。横杆间隔法(如下he-he-da)
代码:
<!DOCTYPE html><html><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Hello World! heheheheheheda</title> <script src="https://unpkg.com/vue@next"></script></head><body> <div id="heheApp"></div></body><script> const app = Vue.createApp({ data() { return {count: 1} }, methods: { handleItemEvent() { this.count += 1; } }, template: ` <div> <counter :count="count" @he-he-da="handleItemEvent"/> </div>` }); app.component('counter', { props: ['count'], methods: { handleItemClick() { this.$emit('heHeDa'); } }, template:` <div @click="handleItemClick">{{count}}</div> ` }); const vm = app.mount('#heheApp');</script></html>
运行,点击组件:
携带参数的事件 发送和监听回调
可以增加参数位,this.$emit()
父组件的监听回调中,
则可加形参位 用于接收参数(如
中的 handleItemEvent(param)
);param
代码:
<script> const app = Vue.createApp({ data() { return {count: 1} }, methods: { handleItemEvent(param) { this.count += param; } }, template: ` <div> <counter :count="count" @add-count="handleItemEvent"/> </div>` }); app.component('counter', { props: ['count'], methods: { handleItemClick() { this.$emit('addCount', 8); } }, template:` <div @click="handleItemClick">{{count}}</div> ` }); const vm = app.mount('#heheApp');</script>
运行,点击效果:
子组件需 发送多个参数 亦可,只需在
按需增加参数位,this.$emit()
父组件的监听回调中,增加对应的形参 去接收就可:
<script> const app = Vue.createApp({ data() { return {count: 1} }, methods: { handleItemEvent(param1, param2, param3) { this.count = this.count + param1 + param2 + param3; console.log(this.count); } }, template: ` <div> <counter :count="count" @add-count="handleItemEvent"/> </div>` }); app.component('counter', { props: ['count'], methods: { handleItemClick() { this.$emit('addCount', 8, 2, 6); } }, template:` <div @click="handleItemClick">{{count}}</div> ` }); const vm = app.mount('#heheApp');</script>
效果:
当然 父组件 接收 子组件参数 后的 计算逻辑,
可以在 子组件传参 的时候 计算完成 再传给
!this.$emit()
父组件接收时,直接 受值就可(
);handleItemEvent(count)
<script> const app = Vue.createApp({ data() { return {count: 1} }, methods: { handleItemEvent(count) { this.count = count; console.log(this.count); } }, template: ` <div> <counter :count="count" @add-count="handleItemEvent"/> </div>` }); app.component('counter', { props: ['count'], methods: { handleItemClick() { this.$emit('addCount', this.count + 16); } }, template:` <div @click="handleItemClick">{{count}}</div> ` }); const vm = app.mount('#heheApp');</script>
效果同上一个例子;
使用 组件的
emits
板块 整理组件事件实际开发场景中,我们一个组件自己设置的触发事件可能会很多,
我们不可能一个一个去梳理核实,
这个时候即可以使用 组件的
板块 来整理组件的事件;emits
可以把组件中
都写在这里,自己设置到的事件
,提高方便梳理
,可读性
或者者把
写在这里,想要定义的事件
如此一来,假如
编写对应的自己设置事件,不记得
Vue系统会在运行时 给予
:警告
<script> const app = Vue.createApp({ data() { return {count: 1} }, methods: { handleItemEvent(count) { this.count = count; console.log(this.count); } }, template: ` <div> <counter :count="count" @add-count="handleItemEvent"/> </div>` }); app.component('counter', { props: ['count'], emits: ['hehehe'], methods: { handleItemClick() { this.$emit('addCount', this.count + 16); } }, template:` <div @click="handleItemClick">{{count}}</div> ` }); const vm = app.mount('#heheApp');</script>
假如
编写对应的自己设置事件,Vue系统会在运行时 给予不记得
:警告
使用 组件
emits
板块的 Object
形式 校验外传的参数值可以根据需要,使用 组件
板块的 emits
形式 校验外传的参数值,Object
如下,子组件的
板块,emits
‘key’值定义对应的事件名,‘value’值定义一个校验函数,
返回
表示同意数值外传,true
返回
表示不同意,会给出警告;false
<script> const app = Vue.createApp({ data() { return {count: 1} }, methods: { handleItemEvent(count) { this.count = count; console.log(this.count); } }, template: ` <div> <counter :count="count" @add-count="handleItemEvent"/> </div>` }); app.component('counter', { props: ['count'], emits: { addCount: (count) => { if (count < 0) { return true; } return false; } }, methods: { handleItemClick() { this.$emit('addCount', this.count + 16); } }, template:` <div @click="handleItemClick">{{count}}</div> ` }); const vm = app.mount('#heheApp');</script>
运行,点击效果:
结合
$emit
、v-bind
与v-model
实现 父子组件通信(数据双向绑定)v-model可以实现数据字段与DOM节点内容的双向绑定,
也可以实现数据字段与数据字段之间的双向绑定;
而只能是实现v-bind
;单向数据流
若不自己设置
,则需要用承接的字段名
作为默认的modelValue
;承接字段名
同时,
的一参默认为$emit()
,二参为绑定的数据;update:modelValue
如下代码,
子组件 的承接变量
同父组件的modelValue
字段 双向绑定,count
(实际上就是
的特性 —— 将 子组件的内容即v-model
同 父组件的modelValue
双向绑定)数据字段
而后显示在子组件的DOM中(
):{{modelValue}}
<script> const app = Vue.createApp({ data() { return {count: 1} }, template: ` <counter v-model="count"/>` }); app.component('counter', { props: ['modelValue'], methods: { handleItemClick() { this.$emit('update:modelValue', this.modelValue + 16); console.log(vm.$data.count); } }, template:` <div @click="handleItemClick">{{modelValue}}</div> ` }); const vm = app.mount('#heheApp');</script>
效果:
当然也可以
,自己设置字段名
这种方式需要给
字段接一个字段名,v-model
同时将这个字段名替代子组件中所有
的位置:modelValue
<script> const app = Vue.createApp({ data() { return {count: 1} }, template: ` <counter v-model:testField="count"/>` }); app.component('counter', { props: ['testField'], methods: { handleItemClick() { this.$emit('update:testField', this.testField + 16); console.log(vm.$data.count); } }, template:` <div @click="handleItemClick">{{testField}}</div> ` }); const vm = app.mount('#heheApp');</script>
实现效果与上例相同;
结合
$emit
、v-bind
与v-model
实现 父子组件通信(多个字段的应用案例)如下代码,
父组件的
与子组件承接的count
字段,testField
父组件的
与子组件承接的count1
字段,testField1
分别实现了双向绑定:
<script> const app = Vue.createApp({ data() { return { count: 1, count1: 1 } }, template: ` <counter v-model:testField="count" v-model:testField1="count1"/>` }); app.component('counter', { props: ['testField','testField1'], methods: { handleItemClick() { this.$emit('update:testField', this.testField + 16); console.log("vm.$data.count", vm.$data.count); }, handleItemClick1() { this.$emit('update:testField1', this.testField1 + 8); console.log("vm.$data.count1", vm.$data.count1); } }, template:` <div @click="handleItemClick">{{testField}}</div> <div @click="handleItemClick1">{{testField1}}</div> ` }); const vm = app.mount('#heheApp');</script>
效果:
自己设置修饰符
机制:在父组件调用处,在
后 使用v-model
,自己设置修饰符
在的地方,如点击事件中,实现修饰符逻辑
通过返回的this.modelModifiers.[自己设置修饰符名]
,布尔值
判断客户能否使用了修饰符,
进而分别对使用与否做相应的解决;
另外板块中可以'modelModifiers'
(下代码指定为一个空对象指定默认值
);{}
试验
this.modelModifiers
的作用首先下面是一个空的解决,
板块中'modelModifiers'
(下代码指定为一个空对象指定默认值
),{}
函数中打印 子组件mounted
属性的内容,modelModifiers
代码如下,
运行后,可以见打印了一个对象
,{captalize: true}
正是我们传入的自己设置修饰符
(这里未做解决).captalize
【假如这里
不接修饰符,v-model
将打印一个空对象console.log(this.modelModifiers);
】:{}
<script> const app = Vue.createApp({ data() { return { char: 'a' } }, template: ` <counter v-model.captalize="char"/>` }); app.component('counter', { props: { 'modelValue': String, 'modelModifiers': { default: () => ({}) } }, mounted() { console.log(this.modelModifiers); }, methods: { handleClick() { this.$emit('update:modelValue', this.modelValue + 'h'); console.log("vm.$data.count", vm.$data.char); } }, template:` <div @click="handleClick">{{modelValue}}</div> ` }); const vm = app.mount('#heheApp');</script>
下面在子组件的点击回调
handleClick()
中,通过this.modelModifiers.[自己设置修饰符名]
实现自己设置修饰符逻辑实现效果即 点击之后使得对应的字符串 全变大写;
<script> const app = Vue.createApp({ data() { return { testString: 'a' } }, template: ` <counter v-model.heheda="testString"/>` }); app.component('counter', { props: { 'modelValue': String, 'modelModifiers': { default: () => ({}) } }, mounted() { console.log(this.modelModifiers); }, methods: { handleClick() { let newValue = this.modelValue + 'h'; if(this.modelModifiers.heheda) { newValue = newValue.toUpperCase(); } this.$emit('update:modelValue', newValue); console.log("vm.$data.count", vm.$data.testString); } }, template:` <div @click="handleClick">{{modelValue}}</div> ` }); const vm = app.mount('#heheApp');</script>
效果:
插槽【slot】【传组件示例】
使用关键 主要分两个部分:
自己设置子组件:
在需要 被父组件的位置,插入组件
使用标签对临时占位;<slot></slot>
父组件:
在调用时,子组件标签对
往间子组件标签对
写上 要替换中子组件标签对
位置的组件<slot></slot>
【slot】的出现,
方便父子组件之间数据的传递,
方便DOM的传递;
<!DOCTYPE html><html><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Hello World! heheheheheheda</title> <script src="https://unpkg.com/vue@next"></script></head><body> <div id="heheApp"></div></body><script> const app = Vue.createApp({ template: ` <myform> <div>提交</div> </myform> <myform> <button>提交</button> </myform>` }); app.component('myform', { template:` <div> <input /> <slot></slot> <br><br> </div> ` }); const vm = app.mount('#heheApp');</script></html>
运行效果:
注意,slot标签上是无法直接增加事件(修饰符)的,如有需要,可以在<slot>外层包裹一层<span>标签,再加上事件
<script> const app = Vue.createApp({ template: ` <myform> <div>提交</div> </myform> <myform> <button>提交</button> </myform>` }); app.component('myform', { methods: { handleClick() { console.log("heheda!!==="); } }, template:` <div> <input /> <span @click="handleClick"> <slot></slot> </span> <br><br> </div> ` }); const vm = app.mount('#heheApp');</script&
相关文章