Rumah > hujung hadapan web > View.js > teks badan

Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen

PHPz
Lepaskan: 2023-05-15 09:28:05
ke hadapan
2918 orang telah melayarinya

Ringkasan artikel ini

  • Komponen ibu bapa dan anak boleh berkomunikasi melalui acara

  • Bawa acara Parameter menghantar dan mendengar panggilan balik

  • Gunakan bahagian emits komponen untuk mengatur acara komponen

  • Gunakan borang emits bahagian Object komponen untuk mengesahkan nilai parameter yang diluluskan

  • Gabungkan $emit, v-bind dan v-model Realisasikan komunikasi komponen ibu bapa-anak (pengikatan data dua hala)

  • Gabungkan $emit, v-bind dan v-model untuk merealisasikan ibu bapa -komunikasi komponen kanak-kanak (aplikasi pelbagai medan Kes)

  • Tetapkan pengubah suai sendiri

    • Eksperimen this.modelModifiers Fungsi

  • Di bawah, dalam panggilan balik klik handleClick() sub-komponen, laksanakan logik pengubah suai anda sendiri this.modelModifiers.[自己设置修饰符名] melalui

  • Slot [slot] [Contoh komponen yang melepasi]

  • Ambil perhatian bahawa acara tidak boleh ditambah terus pada teg slot (pengubah suai), jika perlu, anda boleh membalut teg di luar <slot> dan memasukkan acara

  • Slot [Contoh menghantar rentetan]

  • Slot [Contoh menghantar subkomponen untuk menetapkan sendiri]

  • Isu skop slot

  • Nilai lalai UI Slot

  • Masukkan Pemisahan fleksibel dan penggunaan slot [Slot bernama]

  • v-slotSingkatan perintah

  • Contoh v-for biasa untuk pemaparan senarai

  • v-forDigabungkan dengan v-bind, v-slot, <slot></slot> untuk pemaparan senarai

  • Gunakan konsep 解构 untuk singkatan

  • Komponen dinamik

    • Penggunaan konvensional 双向绑定特性, menukar UI melalui acara klik

    • Dinamik penulisan komponen

  • Komponen tak segerak

Komponen ibu bapa dan anak boleh berkomunikasi melalui acara

Nota sebelumnya - "Vue3 | Definisi dan kebolehgunaan semula komponen, komponen tempatan, komponen global, pemindahan nilai antara komponen dan pengesahan, aliran data tunggal, Atribut bukan prop", sehala Konsep aliran data,
bermakna komponen anak tidak boleh mengubah suai medan data daripada komponen induk

Jika anda benar-benar ingin mengubah suainya, anda boleh berkomunikasi dengan cara berikut:
Pertama, dalam. UI komponen anak Dalam kaedah panggil balik klik, this.$emit('【自己设置事件名】') dipanggil dan
menghantar 事件 ke luar

kemudian komponen induk di semua peringkat akan menerima acara ini dan memanggil tag komponen anak dalam komponen induk Pada,
dalam bentuk
, @【事件名】= "回调方法名" acara dan konfigurasi 监听; dalam 回调方法
, anda boleh mengubah suai data komponen induk medan yang ingin diubah suai oleh komponen kanak-kanak; 回调方法.

Kod:

<!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(&#39;counter&#39;, {        props: [&#39;count&#39;],        methods: {            handleItemClick() {                this.$emit(&#39;heHeDa&#39;);            }        },        template:`        <div @click="handleItemClick">{{count}}</div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script></html>
Salin selepas log masuk

Jalankan, klik pada komponen: 驼峰命名法
横杆间隔法(如下he-he-da)Acara menghantar dan mendengar panggilan balik dengan parameter

boleh menambah bit parameter Dalam panggilan balik pendengaran komponen induk

,

boleh menambah bit parameter formal untuk menerima parameter (seperti Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen dalam

); >

Kod:

<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(&#39;counter&#39;, {        props: [&#39;count&#39;],        methods: {            handleItemClick() {                this.$emit(&#39;addCount&#39;, 8);            }        },        template:`        <div @click="handleItemClick">{{count}}</div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script>
Salin selepas log masuk

Jalankan, kesan klik: this.$emit()

handleItemEvent(param)param
Sub-komponen juga boleh menghantar berbilang parameter, hanya Anda perlu menambah bit parameter seperti yang diperlukan dalam

Dalam panggilan balik mendengar komponen induk

, cuma tambah parameter formal yang sepadan untuk menerima:

<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(&#39;counter&#39;, {        props: [&#39;count&#39;],        methods: {            handleItemClick() {                this.$emit(&#39;addCount&#39;, 8, 2, 6);            }        },        template:`        <div @click="handleItemClick">{{count}}</div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script>
Salin selepas log masuk
Kesan:

Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen
Sudah tentu, logik pengiraan selepas komponen induk menerima parameter sub-komponen, this.$emit() boleh dikira dan kemudian dihantar ke
apabila sub-komponen melepasi parameter!
Apabila komponen induk menerimanya, terima sahaja nilainya secara langsung (

);

使用 组件的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(&#39;counter&#39;, {        props: [&#39;count&#39;],        emits: [&#39;hehehe&#39;],        methods: {            handleItemClick() {                this.$emit(&#39;addCount&#39;, this.count + 16);            }        },        template:`        <div @click="handleItemClick">{{count}}</div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script>
Salin selepas log masuk

假如不记得编写对应的自己设置事件,Vue系统会在运行时 给予警告

Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen

使用 组件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(&#39;counter&#39;, {        props: [&#39;count&#39;],        emits: {            addCount: (count) => {                if (count < 0) {                    return true;                }                return false;            }        },        methods: {            handleItemClick() {                this.$emit(&#39;addCount&#39;, this.count + 16);            }        },        template:`        <div @click="handleItemClick">{{count}}</div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script>
Salin selepas log masuk

运行,点击效果:Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen

结合$emitv-bindv-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(&#39;counter&#39;, {        props: [&#39;modelValue&#39;],        methods: {            handleItemClick() {                this.$emit(&#39;update:modelValue&#39;, this.modelValue + 16);                console.log(vm.$data.count);            }        },        template:`        <div @click="handleItemClick">{{modelValue}}</div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script>
Salin selepas log masuk

效果:Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen

当然也可以自己设置字段名
这种方式需要给v-model字段接一个字段名,
同时将这个字段名替代子组件中所有modelValue的位置:

<script>    const app = Vue.createApp({        data() {            return {count: 1}        },        template: `            <counter v-model:testField="count"/>`    });    app.component(&#39;counter&#39;, {        props: [&#39;testField&#39;],        methods: {            handleItemClick() {                this.$emit(&#39;update:testField&#39;, this.testField + 16);                console.log(vm.$data.count);            }        },        template:`        <div @click="handleItemClick">{{testField}}</div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script>
Salin selepas log masuk

实现效果与上例相同;

结合$emitv-bindv-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(&#39;counter&#39;, {        props: [&#39;testField&#39;,&#39;testField1&#39;],        methods: {            handleItemClick() {                this.$emit(&#39;update:testField&#39;, this.testField + 16);                console.log("vm.$data.count", vm.$data.count);            },            handleItemClick1() {                this.$emit(&#39;update:testField1&#39;, 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(&#39;#heheApp&#39;);</script>
Salin selepas log masuk

效果:Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen

自己设置修饰符

机制:在父组件调用处,在v-model后 使用自己设置修饰符
实现修饰符逻辑的地方,如点击事件中,
通过this.modelModifiers.[自己设置修饰符名]返回的布尔值
判断客户能否使用了修饰符,
进而分别对使用与否做相应的解决;
另外&#39;modelModifiers&#39;板块中可以指定默认值(下代码指定为一个空对象{});

试验this.modelModifiers的作用

首先下面是一个空的解决,&#39;modelModifiers&#39;板块中指定默认值(下代码指定为一个空对象{}),
mounted函数中打印 子组件modelModifiers属性的内容,

代码如下,
运行后,可以见打印了一个对象{captalize: true}
正是我们传入的自己设置修饰符.captalize(这里未做解决)
【假如这里v-model不接修饰符,
console.log(this.modelModifiers);将打印一个空对象{}】:

<script>    const app = Vue.createApp({        data() {            return {                char: &#39;a&#39;            }        },        template: `            <counter v-model.captalize="char"/>`    });    app.component(&#39;counter&#39;, {        props: {            &#39;modelValue&#39;: String,            &#39;modelModifiers&#39;: {                default: () => ({})            }        },        mounted() {            console.log(this.modelModifiers);        },        methods: {            handleClick() {                this.$emit(&#39;update:modelValue&#39;, this.modelValue + &#39;h&#39;);                console.log("vm.$data.count", vm.$data.char);            }        },        template:`        <div @click="handleClick">{{modelValue}}</div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script>
Salin selepas log masuk

Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen

下面在子组件的点击回调handleClick()中,通过this.modelModifiers.[自己设置修饰符名]实现自己设置修饰符逻辑

实现效果即 点击之后使得对应的字符串 全变大写;

<script>    const app = Vue.createApp({        data() {            return {                testString: &#39;a&#39;            }        },        template: `            <counter v-model.heheda="testString"/>`    });    app.component(&#39;counter&#39;, {        props: {            &#39;modelValue&#39;: String,            &#39;modelModifiers&#39;: {                default: () => ({})            }        },        mounted() {            console.log(this.modelModifiers);        },        methods: {            handleClick() {                let newValue = this.modelValue + &#39;h&#39;;                if(this.modelModifiers.heheda) {                    newValue = newValue.toUpperCase();                }                this.$emit(&#39;update:modelValue&#39;, newValue);                console.log("vm.$data.count", vm.$data.testString);            }        },        template:`        <div @click="handleClick">{{modelValue}}</div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script>
Salin selepas log masuk

效果:

Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen

插槽【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(&#39;myform&#39;, {        template:`        <div>            <input />            <slot></slot>            <br><br>        </div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script></html>
Salin selepas log masuk

运行效果:Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen

注意,slot标签上是无法直接增加事件(修饰符)的,如有需要,可以在<slot>外层包裹一层标签,再加上事件

<script>    const app = Vue.createApp({        template: `            <myform>                <div>提交</div>            </myform>            <myform>                <button>提交</button>            </myform>`    });    app.component(&#39;myform&#39;, {        methods: {            handleClick() {                console.log("heheda!!===");            }        },        template:`        <div>            <input />            <span @click="handleClick">                <slot></slot>            </span>                <br><br>        </div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script>
Salin selepas log masuk

运行,点击提交文本或者按钮:Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen

插槽【传 字符串示例】

<script>    const app = Vue.createApp({        template: `            <myform>                66666            </myform>            <myform>                88888            </myform>`    });    app.component(&#39;myform&#39;, {        methods: {            handleClick() {                console.log("heheda!!===");            }        },        template:`        <div>            <input />            <span @click="handleClick">                <slot></slot>            </span>                <br><br>        </div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script>
Salin selepas log masuk

Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen

插槽【传 自己设置子组件 示例】

<script>    const app = Vue.createApp({        template: `            <myform>                <test />            </myform>            <myform>                88888            </myform>`    });    app.component(&#39;test&#39;, {        template: `<div>test component</div>`    })    app.component(&#39;myform&#39;, {        methods: {            handleClick() {                console.log("heheda!!===");            }        },        template:`        <div>            <input />            <span @click="handleClick">                <slot></slot>            </span>                <br><br>        </div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script>
Salin selepas log masuk

运行:Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen

插槽作用域问题

尽管,父组件中 往子组件标签间 插入的组件 会替换子组件的插槽位,
但是父组件中 往子组件标签间 插入的组件,
其所使用的数据字段,依然是父组件的,而非子组件

父组件的template中 调用的数据是 父组件中的 data;
子组件的template中 调用的数据是 子组件中的 data;

<script>    const app = Vue.createApp({        data() {            return {                text: &#39;提交&#39;            }        },        template: `            <myform>                <div>{{text}}</div>            </myform>            <myform>                <button>{{text}}</button>            </myform>`    });    app.component(&#39;myform&#39;, {        methods: {            handleClick() {                console.log("heheda!!===");            }        },        template:`        <div>            <input />            <span @click="handleClick">                <slot></slot>            </span>                <br><br>        </div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script>
Salin selepas log masuk

Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen

插槽 UI默认值

可以在子组件的插槽<slot>标签间 编写默认值
假如父组件没有使用 组件 注入插槽
则对应位置 会显示默认值

<script>    const app = Vue.createApp({        data() {            return {                text: &#39;提交&#39;            }        },        template: `            <myform>                <div>{{text}}</div>            </myform>            <myform>                <button>{{text}}</button>            </myform>            <myform>            </myform>`    });    app.component(&#39;myform&#39;, {        methods: {            handleClick() {                console.log("heheda!!===");            }        },        template:`        <div>            <input />            <span @click="handleClick">                <slot>default value</slot>            </span>                <br><br>        </div>        `    });    const vm = app.mount(&#39;#heheApp&#39;);</script>
Salin selepas log masuk

效果:Kaedah untuk komunikasi antara komponen ibu bapa dan anak Vue3 dan pengikatan dua hala antara komponen

插槽的灵活拆分与应用【具名插槽】

  • 使得插槽的 父组件注入部分 和 子组件占位部分,能够更加灵活的布局,

    可以通过v-slot:[插槽名]来对一组插槽命名,
    父组件定义之后 插槽名及其对应的组件之后,

    子组件只要要在要占位的地方,
    配合name属性 使用对应命名的<slot>标签,
    就可将对应的父组件插槽组件占用过来;

  • 父组件 的插槽注入部分的组件,
    需要用