Vue: Alat peraga yang disediakan tidak disuntikkan ke dalam komponen fungsional

Dibuat pada 7 Jun 2017  ·  16Komentar  ·  Sumber: vuejs/vue

Versi: kapan

2.3.3

Tautan reproduksi

http://jsfiddle.net/p861bj9y/

Langkah-langkah untuk mereproduksi

Saya membuat reproduksi minimal dari perilaku yang saya coba uji, contohnya hanya memerlukan JSX agar berfungsi.

Apa yang diharapkan?

Properti yang diturunkan dari induk akan muncul di ctx.injections .

Apa yang sebenarnya terjadi?

Ctx.injections ada tapi tetap kosong. Properti tidak diturunkan ke konteks komponen fungsional.

bug

Komentar yang paling membantu

Apakah ada rencana untuk mengatasi masalah ini di v3?

Misalnya saya mencoba mengabstraksi v-for menjadi fungsi render tetapi anak-anak saya dapat menjadi komponen fungsional (jadi mereka sudah dirender saat memasuki fungsi render dan saya tidak dapat mengkloningnya).

Semua 16 komentar

Itu karena alih-alih parent , child dianggap sebagai anak-anak dari vm (mungkin masalah). Jadi, Anda mungkin perlu menulis provide di vm .

BTW, biola Anda menggunakan [email protected] 😅

Algoritme pencarian untuk memberikan suntikan adalah anak melihat dirinya sendiri untuk atribut yang disediakan dan kemudian mengulang hierarki $parent untuk mencari alat peraga yang disediakan hingga berada di root.
https://github.com/vuejs/vue/blob/b182ac40697edbe8253d4bd68b6ac09e93259e1c/src/core/instance/inject.js#L59 -L59

Tidak bisa menjalankan biola Anda, tetapi ketika saya menjalankan https://jsfiddle.net/Austio/vhgztp59/7/ biola ini $ parent tidak ditentukan pada komponen anak ketika saya sampai ke konteks pencarian. Setidaknya itu adalah permulaan jika ini bukan masalah dengan rendering ke dalam slot dan tidak ada hubungan antar komponen.

sepertinya komponen fungsional ditampilkan sebelum slot diselesaikan

@Kingwl benar, dan itu semacam persyaratan teknis.

Saya ingat saya mengemukakan hal itu karena saya semakin tergila-gila padanya. Pada akhirnya, itu tampak normal bagi saya karena komponen fungsional dilampirkan ke komponen tempat mereka dirender dan oleh karena itu ketika digunakan dalam slot, mereka melekat ke komponen luar. Namun, tidak demikian halnya dengan komponen non-fungsional:

Kontainer menginjeksi mode: 'foo' dan menghasilkan <div><slot/></div>

<!-- rendered in App -->
<container>
   <!-- parent is App, mode is undefined -->
  <functional></functional>
</container>

<container>
   <!-- parent is container, mode is foo -->
  <not-functional></not-functional>
</container>

http://jsfiddle.net/p861bj9y/

edit: @alidcastano Saya memperbarui biola di komentar Anda karena komentar Anda bahkan tidak menggunakan Vue 2

Haha maaf karena telah menggunakan versi Vue yang salah di biola, saya terlalu terjebak karena tidak dapat mengkonfigurasi JSX yang tidak saya sadari. @posva Terima kasih telah memperbaiki contoh saya!

-

Jadi masalahnya di sini bukanlah bahwa komponen fungsional tidak dapat menerima properti yang disediakan, apakah komponen fungsional itu diberikan sebelum slot?

@LinusBorg Dengan "persyaratan teknis" apakah itu berarti bahwa tidak ada solusi atau perilaku yang dimaksudkan?

Haruskah sebuah wadah dibuat untuk melayani sebagai vm yang melewati props? Misalnya, desainnya akan berubah menjadi ini:

// before
<parent-component>
  <child-component />
</parent-component>

// after
<vm-container>
   <parent-component>
     <child-component />
   </parent-component>
<vm-container>

Tetapi contoh di atas tampaknya tidak perlu membengkak karena esensi dari komponen induk sudah mencakup semua data yang diperlukan untuk diberikan kepada anak. Tapi saya terbuka untuk diskusi; apakah ini yang kalian sarankan?

vm-container tidak akan mengubah apapun karena slot ditampilkan dalam konteks app

Yang dimaksud dengan "persyaratan teknis" apakah itu berarti bahwa tidak ada solusi atau perilaku yang dimaksudkan?

Perilaku tersebut merupakan hasil dari cara kerja komponen fungsional. Pertimbangkan kumpulan komponen ini:

<!-- template of a `parent` component -->
<template>
  <Child>
    <functional />
  </Child>
</template>

Saat Anda meneruskan komponen fungsional ke slot komponen lain, komponen tersebut harus dirender sebelum diteruskan ke turunan, sehingga komponen turunan tersebut dapat menerima vNodes yang dihasilkan sebagai konten slot. (*)

Dalam konteks contoh saya di atas, itu berarti bahwa pada saat komponen <functional> dirender, induk yang tersedia adalah komponen luar ( <parent> ), bukan <child> .

Akibatnya, satu-satunya suntikan yang tersedia untuk komponen fungsional adalah suntikan yang juga tersedia dalam <parent> .


(*): Begitulah cara implementasi saat ini dari virtualdom bekerja dengan komponen fungsional. Untuk mengubahnya akan membutuhkan perubahan yang cukup banyak dari mekanisme internal.

@posva @LinusBorg Mengerti, terima kasih telah menjelaskan.

Jadi karena persyaratan ini, satu-satunya cara untuk menggunakan menyediakan / menyuntikkan dengan komponen fungsional adalah dengan memiliki props yang disediakan dalam konteks app .

Saya yakin kendala ini akan dijelaskan dalam dokumentasi. Silakan lanjutkan dan tutup masalah ini jika tidak ada hal lain yang perlu dilakukan atau diklarifikasi; Terima kasih lagi!

Mungkin kita bisa menemukan cara untuk meningkatkan komponen fungsional pada slot
Tetapi untuk saat ini, itu harus dilakukan seperti @posva dan @LinusBorg berkata

@Kingw Terima kasih telah menjaga ini tetap terbuka.

Saya akhirnya punya waktu untuk mencoba memasukkan ini ke dalam plugin vue-mobiledoc-editor saya menggunakan saran di atas. Satu masalah yang saya perkirakan jika komponen perlu digunakan dari instance app , adalah lebih sulit untuk mengizinkan fleksibilitas dengan komponen bersarang yang digunakan.

Misalnya, saya harus mengekspor komponen yang sudah terdaftar di bawah instance app:

...

export default Vue.extend({
  render (h) {
    return (
      <div>
        <ParentComp>
          <ChildFuncComp/>
        </ParentComp>
      </div>
    )
  },

  provide () { // data that needs to be injected into functional components 
    return {
       msg: 'hello'
    }
  },

  components: {
    ParentComp,
    ChildFuncComp
  }
})

Kemudian dari pemahaman saya, saat pengguna menggunakan plugin, akan seperti ini:

// template
<div id="app">
   <div id="#someWhereInApp" />
</div>

// script 
import SuperCoolComponent from 'SuperCoolComponent' 

export default {
   mounted () {
    this.$once('mounted', () => new SuperCoolComponent().$mount('#someWhereInApp'))
    this.$emit('mounted')
  }
}

Jika implementasi saya benar maka ini sangat membatasi penggunaan penyediaan / injeksi dengan komponen fungsional karena Anda tidak diizinkan untuk mengimpor dan mendaftarkan komponen yang ingin Anda gunakan.

Saya akan menggunakan komponen lengkap sebagai gantinya untuk mendukung penyediaan / injeksi

Saya mencoba untuk menyelesaikan ini
mungkin Ini proses yang panjang🌚

@Kingwl Apakah Anda dapat menyelesaikannya?

Apakah ada rencana untuk mengatasi masalah ini di v3?

Misalnya saya mencoba mengabstraksi v-for menjadi fungsi render tetapi anak-anak saya dapat menjadi komponen fungsional (jadi mereka sudah dirender saat memasuki fungsi render dan saya tidak dapat mengkloningnya).

Perubahan apapun?

Apakah halaman ini membantu?
0 / 5 - 0 peringkat