2.4.2
https://jsfiddle.net/o7yvL2jd/
Saya telah mencari cara yang tepat untuk mengimplementasikan HoC dengan vue.js. Tetapi tidak dapat menemukan contoh yang cocok.
Tautan di bawah ini adalah implementasi HoC yang diketahui. Tapi tidak bekerja diharapkan.
https://jsfiddle.net/o7yvL2jd/
Bagaimana saya bisa mengimplementasikan HoC dengan vue.js?
Saya hanya ingin tahu bagaimana menerapkan HoC dengan cara react.js.
Mereka adalah HoC yang hanya membuat komponen yang diteruskan sebagai parameter.
HoC yang berisi slot dan event akan dirender secara normal.
Elemen yang akan dirender tidak ada, atau urutan yang dirender berbeda dari komponen dasar.
Beberapa implementasi HoC tidak bekerja dengan event handler.
Halo @eu81273
Terima kasih atas minat Anda pada proyek ini.
Namun, masalah Anda adalah pertanyaan penggunaan/dukungan, dan pelacak masalah disediakan khusus untuk laporan bug dan permintaan fitur (seperti yang diuraikan dalam Panduan Berkontribusi kami).
Kami mendorong Anda untuk menanyakannya di forum , Stack Overflow atau di obrolan perselisihan kami dan dengan senang hati membantu Anda di luar sana.
FWIW, saya melihat keluar dari kepentingan pribadi - ini harus bekerja 100% dari kasus.
const HOC = WrappedComponent => ({
props: typeof WrappedComponent === 'function' // accept both a construtor and an options object
? WrappedComponent.options.props
: WrappedComponent.props,
render (h) {
// reduce all slots to a single array again.
const slots = Object.keys(this.$slots).reduce((arr, key) => arr.concat(this.$slots[key]), []);
return h(WrappedComponent, {
attrs: this.$attrs,
props: this.$props,
on: this.$listeners,
}, slots);
}
});
Saya mengedit HOC04 dalam contoh Anda karena itu yang paling dekat dengan solusi:
https://jsfiddle.net/Linusborg/o7yvL2jd/22/
Sunting: masih ada masalah dengan slot, selidiki ...
Saya mungkin telah menyelesaikannya: https://jsfiddle.net/BogdanL/ucpz8ph4/ . Slot baru saja di-hardcode sekarang, tapi itu sepele untuk dipecahkan.
Tampaknya solusinya ada di sepanjang metode @lbogdan tetapi createElement harus memiliki cara mengambil slot, seperti halnya dapat mengambil scopedSlots.
Namun, _masih_ banyak usaha untuk membuat HoC. Ada banyak hal yang harus diingat untuk dilalui, sementara dengan reaksi Anda hanya membuat WrappedComponent dengan props.
Saya baru saja memikirkan solusi yang sangat sederhana ... beri tahu saya jika saya melewatkan sesuatu di sini:
const HOC06 = WrappedComponent => Vue.extend({
mounted () {
console.log('mounted 6')
},
...WrappedComponent
})
Berdasarkan contoh yang diberikan oleh @LinusBorg dan @lbogdan , implementasi HoC paling minimal yang dapat menangani komponen dengan slot adalah:
const HoC = WrappedComponent => ({
props: typeof WrappedComponent === 'function'
? WrappedComponent.options.props
: WrappedComponent.props,
render (h) {
const slots = this.$slots;
const scopedSlots = {};
Object.keys(slots).map(key => (scopedSlots[key] = () => slots[key]));
return h(WrappedComponent, {
attrs: this.$attrs,
props: this.$props,
on: this.$listeners,
scopedSlots,
});
}
});
Seperti yang disebutkan @blocka , masih banyak upaya untuk membuat HoC dengan vue.js.
@eu81273
const HOC06 = WrappedComponent => Vue.extend({
mounted () {
console.log('mounted 6')
},
...WrappedComponent
})
Ini tampaknya lulus ujian Anda, bukan? Tentu saja, Anda harus menyesuaikannya tergantung pada apakah WrappedComponent adalah konstruktor atau objek, tetapi tidak perlu melewatkan slot, acara, atau properti.
masih banyak upaya untuk membuat HoC dengan vue.js.
Terlepas dari masalah slot, ini hanya karena fakta bahwa Vue memang memiliki API yang lebih kompleks daripada React, yang dalam skenario ini merupakan kerugian. Saya mengagumi API minimal Reacts dalam kasus penggunaan semacam ini - Vue baru saja dirancang dengan tujuan yang sedikit berbeda, jadi HOC tidak datang semudah di React.
Tetapi seharusnya cukup sepele untuk membuat fungsi pembantu createHOC()
yang membungkus pengaturan awal ini untuk Anda, bukan?
Yah, itu benar-benar tergantung apa tujuan akhirnya. Dari apa yang saya pahami, tujuan HoC adalah entah bagaimana mengubah (menghias) komponen asli (WrappedComponent) untuk menambahkan (atau menyuntikkan) alat peraga, metode, pendengar acara, dll. (seperti mixin, sungguh :smile: ). HOC06
varian hanya mengubah definisi komponen, tidak mengubah cara pembuatannya.
@blocka Tujuan dari HOC sering kali adalah untuk mendapatkan status (misalnya dari redux / vuex) dan menyuntikkannya ke props komponen yang dibungkus - yang tidak akan bekerja dengan pendekatan Anda.
@LinusBorg benar. Saya tahu itu terlalu bagus untuk menjadi kenyataan dan bahwa saya melupakan sesuatu yang jelas.
Saya pikir ini contoh yang baik untuk menerapkan kasus penggunaan nyata HoC di Vue: https://github.com/ktsn/vuex-connect.
Vue Hocs akan menjadi nilai tambah yang luar biasa (karena hampir selalu muncul dalam debat vue vs react). Mungkin repo resmi dapat dibuat untuk mengembangkan paket pembuat vue-hoc? Dengan begitu kami dapat mengerjakan implementasi yang kuat, didukung,
Btw, dapatkan cara yang lebih baik: gunakan $createElement dari komponen induk alih-alih milik HOC - ini membuat anak menyelesaikan slot dengan benar:
Lucu, tetapi ada lebih banyak alasan untuk ada beberapa alat resmi jadi kami
tidak semua terus menemukan kembali kode ini.
Pada hari Minggu, 30 Juli 2017 pukul 16.33, Thorsten Lü[email protected]
menulis:
Btw, dapatkan cara yang lebih baik: gunakan $createElement dari komponen induk
alih-alih milik HOC - ini membuat anak menyelesaikan slot dengan benar:https://jsfiddle.net/o7yvL2jd/23/
—
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/vuejs/vue/issues/6201#issuecomment-318927628 , atau bisukan
benang
https://github.com/notifications/unsubscribe-auth/AACoury4Fix2jsX_lyTsS6CYOiHJaOuVks5sTOiugaJpZM4Oh0Ij
.
Saya minta maaf karena belum memberikan solusi resmi. Senang Anda pikir itu lucu sekalipun.
Solusi saya juga tidak sempurna, ada masalah lain yang harus diselesaikan - yaitu slot yang dicakup tidak akan berfungsi dengan trik terbaru saya.
edit: oh, tidak apa-apa, mereka bekerja
Solusi resmi mungkin akan dilakukan, setidaknya saya berharap begitu - tetapi harus dipikirkan dan diuji dengan cermat.
Oke, jadi saya bermain-main dengan cara untuk membuatnya lebih mudah.
Lihat di sini: https://jsfiddle.net/Linusborg/j3wyz4d6/
Saya tidak senang dengan API karena ini adalah sketsa ide yang sangat kasar, tetapi dapat melakukan apa pun yang seharusnya dapat dilakukan.
import { createHOC, createRenderFn, normalizeSlots } from 'vue-hoc'
const Component = {
props: ['message']
template: `<p>{{message}}</p>`
}
const HOC = createHOC(Component)
createHOC
akan menangani:
$createElement
dengan itu dari induknya untuk penyelesaian slot yang tepat.Itu sendiri tidak terlalu berguna, tentu saja. Jadi kesenangan terjadi pada argumen kedua yang merupakan objek Komponen sederhana.
Jika Anda ingin menulis fungsi render sendiri, tentu saja bisa. Jika Anda hanya ingin memperluas props, attrs, atau listener, Anda dapat menggunakan helper createRenderFn
. itu akan membuat fungsi render seperti default yang dijelaskan di atas tetapi akan menggabungkan attrs
, props
atau listeners
yang Anda teruskan dengan yang dari induknya.
const HOC = createHOC(Component, {
mounted() {
console.log(`lifecycle hooks work, it's simply component options`)
},
render: createRenderFn(Component, {
props: {
message: 'Hello from your HOC!'
}
}
})
Jika Anda ingin menulis fungsi render Anda sendiri, Anda dapat menggunakan helper normalizeSlots
untuk mengubah objek dari this.$slots
menjadi array yang tepat untuk diteruskan:
const HOC = createHOC(Component, {
render(h) {
return h(Component, {
props: { message: 'hi from HOC'}, // nothing from parent will be passed on
}, normalizeSlots(this.$slots))
}
})
Komentar diinginkan :)
@LinusBorg Sangat bagus!
Apa yang saya pikir akan membantu adalah membuat kasus penggunaan HoC kehidupan nyata dan menyelesaikannya menggunakan primitif ini.
Sangat.
Saya menyebutkan masalah ini (EDIT (mybad): https://github.com/vuejs/vuejs.org/issues/658).
Karena Anda menggunakan $createElement API yang tidak berdokumen, Sebaiknya dokumentasikan untuk pengembang plugin.
Tautan Anda salah (kecuali jika Anda benar-benar ingin menautkan ke masalah dari 2014)
Tapi ya, secara teknis $ceateElement
API masih hilang di halaman API.
@AlexandreBonaventure Masalah itu dari vue 0.x hari. :senyum:
Juga, createElement
didokumentasikan di sini: https://vuejs.org/v2/guide/render-function.html#createElement -Arguments .
Fungsi ini didokumentasikan sebagai argumen dari fungsi render, tetapi tidak tersedia melalui this.$createElement
. Ada masalah terbuka untuk itu di vuejs/vuejs.org/issues/658
@LinusBorg Tapi pada dasarnya fungsi yang sama yang dikirim ke fungsi render()
, kan?
persis sama. Hanya saja tidak didokumentasikan dengan jelas bahwa itu juga tersedia di luar fungsi render melalui metode instance ini.
Saya hanya bermain-main dengan contoh di atas dan ada beberapa masalah saat menggunakannya dalam skenario yang lebih kompleks, oleh karena itu perlunya repo resmi. Beberapa catatan:
withDefaultProps(withProps(component, {}), {})
hoc kedua tidak memiliki akses ke contoh props indukHai teman-teman, saya telah melihat penulisan implementasi ini.
https://github.com/jackmellis/vue-hoc/tree/develop
Beri tahu saya pendapat Anda dan saya akan segera menerbitkannya. Saya juga berpikir untuk menulis paket gaya recompose.
Paket gaya komposisi ulang akan sangat bagus. Benar-benar bisa menggunakan sesuatu
seperti withState baru-baru ini.
Pada Sabtu, 19 Agustus 2017 pukul 05:50, [email protected] menulis:
Hai teman-teman, saya telah melihat penulisan implementasi ini.
https://github.com/jackmellis/vue-hoc/tree/develop
Beri tahu saya pendapat Anda dan saya akan segera menerbitkannya. Saya juga
berpikir tentang menulis paket recompose-style.—
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/vuejs/vue/issues/6201#issuecomment-323513287 , atau bisukan
benang
https://github.com/notifications/unsubscribe-auth/AACoumQWQMgpVeIvzJ3Ti8A4kLBD04Hhks5sZq_zgaJpZM4Oh0Ij
.
@jackmellis Bagus bahwa Anda memimpin ini :)
Beberapa pemikiran tentang umpan balik yang Anda berikan sebelumnya:
Vue.config.optionsMergeStrategies
Saya juga berpikir tentang penamaan. Saya tidak suka createRenderFn
, sesuatu seperti renderComponentWith
akan lebih bermakna dan lebih masuk akal dalam skenario di mana kami menyematkannya di beberapa node lain:
render(h) {
return h('DIV', {staticClass: 'some-styling' }, renderComponentWith({ props: {... } }))
}
createHOC
adalah non-kari komponen pertama, dan kemudian ada varian kari createHOCc
. Ekosistem React sangat berfokus pada fungsi, tidak seperti Vue, yang bertindak lebih seperti kerangka kerja OOP. Jadi saya pikir yang terbaik adalah tetap konsisten dengan Vue lainnya, tetapi tetap menawarkan alternatif fungsional.createRenderFn
karena itulah yang dilakukannya. Tetapi semakin saya menggabungkan ini, semakin sedikit saya pikir orang akan menggunakannya secara langsung. Penggunaan umum akan menjadi seperti:const hoc = createHOC(
Component,
{
created(){
/* ... */
}
},
{
props: (props) => ({
...props,
someProp: 'foo'
})
}
);
Mungkin saya tidak begitu mengerti contoh Anda?
Mungkin saya tidak begitu mengerti contoh Anda?
Tidak, saya pikir Anda berada di jalur yang benar, pikiran saya menuju ke arah yang sama ketika saya memikirkannya lagi setelah balasan terakhir saya.
Dalam POC awal saya, saya memasukkannya sehingga orang dapat menambahkan markup tambahan di sekitar komponen yang dirender, tetapi itu berarti itu bukan HOC lagi, karena akan membawa UI juga ...
Ya, saya pikir Anda mencoba membuat konten tambahan, Anda telah keluar dari wilayah HOC dan mungkin juga membuat SFC untuk menanganinya.
Saya baru saja menerbitkan vue-hoc di npm!
Saya juga sedang mengerjakan vue-compose yang merupakan sesi dokumentasi cepat dari kesiapan juga. Meskipun mirip dengan recompose, Vue menangani banyak hal pintar (seperti komputasi caching dan mendorong penggunaan this
) sehingga sebenarnya tidak memerlukan sintaks yang cukup rumit (atau gaya fungsional).
extends
bekerja secara berbeda, tetapi dapat digunakan untuk mencapai hasil yang serupa, itu benar.
Saya akan menutup ini karena saya pikir proyek @jackmellis memang memberikan dasar yang kuat. Kami tidak bermaksud memasukkan cara untuk membuat HOC menjadi inti, terutama karena kami tidak melihat manfaat besar dari mixin / Extends.
terutama karena kami tidak melihat manfaat besar dari mixin / Extends.
@LinusBorg React telah meninggalkan mixin
, HOC membawa banyak manfaat.
Artikel ini telah menganalisis manfaatnya:
Saya pikir tim Vue harus mempertimbangkan untuk mendukung HoC lebih hati-hati....walaupun tidak mudah (Sepertinya Vue tidak dirancang dengan cara ini).
Saya tidak yakin bahwa HoC adalah konsep yang superior. Potensi bentrokan "kontrak implisit" juga dapat terjadi dengan HoC, misalnya.
Lihat pembicaraan ini Oleh pengelola React-router tentangnya: https://www.youtube.com/watch?v=BcVAq3YFiuc
Meskipun demikian, menurut saya mereka juga tidak buruk , mereka berguna dalam banyak situasi. Mereka bukan peluru ajaib yang mereka puji seperti di dunia React, meskipun, mereka memiliki kelemahannya sendiri.
Seperti yang terlihat dari diskusi di atas, mengimplementasikan HoC di Vue tidak sepele seperti di React karena API dan fungsionalitas Vue lebih luas dan lebih banyak kasus tepi yang harus ditangani.
Kita pasti dapat berbicara tentang bagaimana meningkatkan ini selama tidak perlu merusak apa pun di Vue - HoC tidak layak untuk perubahan besar dalam pandangan saya.
666
implementasi HoC paling minimal yang dapat menangani komponen dengan slot adalah:
function hoc(WrappedComponent) {
return {
render(h) {
return h(WrappedComponent, {
on: this.$listeners,
attrs:this.$attrs,
scopedSlots: this.$scopedSlots,
});
},
};
}
membandingkan dengan jawaban di atas,
saya menulis contoh untuk memeriksa
Komentar yang paling membantu
Oke, jadi saya bermain-main dengan cara untuk membuatnya lebih mudah.
Lihat di sini: https://jsfiddle.net/Linusborg/j3wyz4d6/
Saya tidak senang dengan API karena ini adalah sketsa ide yang sangat kasar, tetapi dapat melakukan apa pun yang seharusnya dapat dilakukan.
createHOC
akan menangani:$createElement
dengan itu dari induknya untuk penyelesaian slot yang tepat.Itu sendiri tidak terlalu berguna, tentu saja. Jadi kesenangan terjadi pada argumen kedua yang merupakan objek Komponen sederhana.
Jika Anda ingin menulis fungsi render sendiri, tentu saja bisa. Jika Anda hanya ingin memperluas props, attrs, atau listener, Anda dapat menggunakan helper
createRenderFn
. itu akan membuat fungsi render seperti default yang dijelaskan di atas tetapi akan menggabungkanattrs
,props
ataulisteners
yang Anda teruskan dengan yang dari induknya.Jika Anda ingin menulis fungsi render Anda sendiri, Anda dapat menggunakan helper
normalizeSlots
untuk mengubah objek darithis.$slots
menjadi array yang tepat untuk diteruskan:Komentar diinginkan :)