Acara tersuai


Halaman ini menganggap anda telah membaca Asas Komponen. Jika anda masih belum tahu banyak tentang komponen, saya syorkan anda membacanya terlebih dahulu.


Direktori


Nama acara

Tidak seperti komponen dan prop, nama acara tidak mempunyai sebarang penukaran kes automatik. Sebaliknya, nama acara yang dicetuskan perlu sepadan dengan nama yang digunakan untuk mendengar acara ini. Contohnya, jika acara dengan nama camelCase dicetuskan:
this.$emit('myEvent')

kemudian mendengar versi kebab-case bagi nama ini tidak akan memberi kesan:
<!-- 没有效果 -->
<my-component v-on:my-event="doSomething"></my-component>

Tidak seperti komponen dan prop, nama acara tidak akan digunakan sebagai JavaScript nama ubah atau nama harta, jadi tiada sebab untuk menggunakan camelCase atau PascalCase. Dan pendengar acara v-on akan ditukar secara automatik kepada semua huruf kecil dalam templat DOM (kerana HTML tidak peka huruf besar-kecil), jadi v-on:myEvent akan menjadi v-on:myevent - menjadikannya mustahil untuk myEvent dipantau.

Oleh itu, kami mengesyorkan agar anda

sentiasa menggunakan nama acara sarung kebab

. . akan menggunakan prop bernama value dan acara bernama input secara lalai, tetapi jenis seperti butang radio dan kotak semak Kawalan input boleh menggunakan nilai atribut untuk Tujuan yang berbezav-on 事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 v-on:myEvent 将会变成 v-on:myevent——导致 myEvent 不可能被监听到。

因此,我们推荐你始终使用 kebab-case 的事件名


自定义组件的 v-model


2.2.0+ 新增

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value 特性用于不同的目的model 选项可以用来避免这样的冲突:

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})

现在在这个组件上使用 v-model 的时候:

<base-checkbox v-model="lovingVue"></base-checkbox>

这里的 lovingVue 的值将会传入这个名为 checked 的 prop。同时当 <base-checkbox> 触发一个 change 事件并附带一个新的值的时候,这个 lovingVue 的属性将会被更新。

注意你仍然需要在组件的 props 选项里声明 checked 这个 prop。


将原生事件绑定到组件


你可能有很多次想要在一个组件的根元素上直接监听一个原生事件。这时,你可以使用 v-on.native. Pilihan model boleh digunakan untuk mengelakkan konflik seperti itu:

<base-input v-on:focus.native="onFocus"></base-input>
🎜Sekarang apabila menggunakan v-model pada komponen ini: 🎜
<label>
  {{ label }}
  <input
    v-bind="$attrs"
    v-bind:value="value"
    v-on:input="$emit('input', $event.target.value)"
  >
</label>
🎜di sini lovingVue Nilai kod> akan dihantar ke prop bernama checked. Pada masa yang sama, apabila <base-checkbox> mencetuskan acara change dengan nilai baharu, sifat lovingVue ini akan dikemas kini . 🎜🎜🎜Perhatikan bahawa anda masih perlu mengisytiharkan prop ditanda dalam pilihan props komponen. . Pada masa ini, anda boleh menggunakan pengubah .native v-on: 🎜
{
  focus: function (event) { /* ... */ }
  input: function (value) { /* ... */ },
}

Ini kadangkala berguna, tetapi ini bukan idea yang baik apabila anda cuba mendengar elemen yang sangat khusus seperti <input>. Sebagai contoh, komponen <base-input> di atas mungkin telah difaktorkan semula seperti berikut, jadi elemen akar sebenarnya ialah elemen <label>: <input> 的非常特定的元素时,这并不是个好主意。比如上述 <base-input> 组件可能做了如下重构,所以根元素实际上是一个 <label> 元素:

Vue.component('base-input', {
  inheritAttrs: false,
  props: ['label', 'value'],
  computed: {
    inputListeners: function () {
      var vm = this
      // `Object.assign` 将所有的对象合并为一个新对象
      return Object.assign({},
        // 我们从父级添加所有的监听器
        this.$listeners,
        // 然后我们添加自定义监听器,
        // 或覆写一些监听器的行为
        {
          // 这里确保组件配合 `v-model` 的工作
          input: function (event) {
            vm.$emit('input', event.target.value)
          }
        }
      )
    }
  },
  template: `
    <label>
      {{ label }}
      <input
        v-bind="$attrs"
        v-bind:value="value"
        v-on="inputListeners"
      >
    </label>
  `
})

这时,父级的 .native 监听器将静默失败。它不会产生任何报错,但是 onFocus 处理函数不会如你预期地被调用。

为了解决这个问题,Vue 提供了一个 $listeners 属性,它是一个对象,里面包含了作用在这个组件上的所有监听器。例如:

this.$emit('update:title', newTitle)

有了这个 $listeners 属性,你就可以配合 v-on="$listeners" 将所有的事件监听器指向这个组件的某个特定的子元素。对于类似 <input> 的你希望它也可以配合 v-model 工作的组件来说,为这些监听器创建一个类似下述 inputListeners 的计算属性通常是非常有用的:

<text-document
  v-bind:title="doc.title"
  v-on:update:title="doc.title = $event"
></text-document>

现在 <base-input> 组件是一个完全透明的包裹器了,也就是说它可以完全像一个普通的 <input> 元素一样使用了:所有跟它相同的特性和监听器的都可以工作。


.sync 修饰符


2.3.0+ 新增

在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以修改父组件,且在父组件和子组件都没有明显的改动来源。

这也是为什么我们推荐以 update:myPropName 的模式触发事件取而代之。举个例子,在一个包含 title prop 的假设的组件中,我们可以用以下方法表达对其赋新值的意图:

<text-document v-bind:title.sync="doc.title"></text-document>

然后父组件可以监听那个事件并根据需要更新一个本地的数据属性。例如:

<text-document v-bind.sync="doc"></text-document>

为了方便起见,我们为这种模式提供一个缩写,即 .sync 修饰符:

rrreee

注意带有 .sync 修饰符的 v-bind 不能和表达式一起使用 (例如 v-bind:title.sync=”doc.title + ‘!’” 是无效的)。取而代之的是,你只能提供你想要绑定的属性名,类似 v-model

当我们用一个对象同时设置多个 prop 的时候,也可以将这个 .sync 修饰符和 v-bindrrreee

At kali ini, pendengar .native Tahap induk akan gagal secara senyap. Ia tidak akan menjana sebarang ralat, tetapi pengendali onFocus tidak akan dipanggil seperti yang anda jangkakan. 🎜🎜Untuk menyelesaikan masalah ini, Vue menyediakan atribut $listeners, iaitu objek yang mengandungi semua pendengar yang bertindak pada komponen ini. Contohnya: 🎜rrreee🎜Dengan atribut $listeners ini, anda boleh menggunakan v-on="$listeners" untuk menghalakan semua pendengar acara ke bahagian tertentu komponen A ini elemen kanak-kanak tertentu. Untuk komponen seperti <input> yang anda mahu gunakan juga dengan v-model, buat inputListeners< seperti berikut untuk pendengar ini Sifat pengiraan /code > selalunya sangat berguna: 🎜rrreee🎜Kini komponen <base-input> ialah pembungkus telus sepenuhnya, yang bermaksud ia boleh digunakan sama seperti < biasa. elemen code><input>: semua atribut dan pendengar yang sama akan berfungsi. 🎜🎜
🎜

.sync Pengubah suai


🎜2.3.0+ Baharu 🎜
🎜Dalam sesetengah Dalam sesetengah kes, kita mungkin perlu melakukan "pengikatan dua hala" pada prop. Malangnya, pengikatan dua hala yang benar menimbulkan masalah penyelenggaraan kerana komponen anak boleh mengubah suai komponen induknya tanpa sumber perubahan yang jelas dalam komponen induk atau anak. 🎜🎜Inilah sebabnya kami mengesyorkan menggunakan mod kemas kini:myPropName untuk mencetuskan acara. Contohnya, dalam komponen hipotesis yang mengandungi prop title, kita boleh menyatakan niat untuk memberikan nilai baharu padanya menggunakan: 🎜rrreee🎜 Komponen induk kemudiannya boleh mendengar acara itu dan mengemas kini mengikut keperluan. Atribut data setempat. Contohnya: 🎜rrreee🎜Untuk kemudahan, kami menyediakan singkatan untuk mod ini, iaitu .sync Pengubah suai: 🎜rrreee
🎜Perhatikan pengubahsuaian dengan .sync < kod>v-bind tidak boleh digunakan dengan ungkapan (cth. v-bind:title.sync="doc.title + '!' ” adalah tidak sah) . Sebaliknya, anda hanya boleh memberikan nama harta yang ingin anda ikat, seperti v-model. 🎜
🎜Apabila kita menggunakan objek untuk menetapkan berbilang prop pada masa yang sama, kita juga boleh menggunakan pengubah suai .sync ini dengan v-bind: 🎜rrreee

Ini akan menghantar setiap atribut (seperti tajuk) dalam objek dokumen sebagai prop bebas, dan kemudian menambah pendengar v-on untuk kemas kini.

akan v-bind.sync 用在一个字面量的对象上,例如 v-bind.sync=”{ title: doc.title }”, tidak berfungsi dengan baik kerana terdapat banyak kes tepi yang perlu dipertimbangkan semasa menghuraikan ungkapan kompleks seperti ini.