Vue: ディスカッションHOCを䜜成するための最良の方法

䜜成日 2017幎07月25日  Â·  40コメント  Â·  ゜ヌス: vuejs/vue

バヌゞョン

2.4.2

耇補リンク

https://jsfiddle.net/o7yvL2jd/

再珟する手順

私はvue.jsでHoCを実装する正しい方法を探しおいたす。 しかし、適切な䟋は芋぀かりたせんでした。
以䞋のリンクは、既知のHoC実装です。 しかし、期埅どおりに機胜したせんでした。
https://jsfiddle.net/o7yvL2jd/

vue.jsでHoCを実装するにはどうすればよいですか
私はreact.jsの方法でHoCを実装する方法を知りたいだけです。

䜕が期埅されたすか

これらは、パラメヌタずしお枡されたコンポヌネントを単玔にレンダリングするHoCです。
スロットずむベントを含むHoCは正垞にレンダリングされたす。

実際に䜕が起こっおいるのですか

レンダリングされる芁玠が欠萜しおいるか、レンダリングされた順序がbaseComponentず異なりたす。
䞀郚のHoC実装は、むベントハンドラヌでは機胜したせん。

discussion

最も参考になるコメント

さお、私はこれを簡単にする方法で遊んだ。

こちらをご芧ください https //jsfiddle.net/Linusborg/j3wyz4d6/

APIは非垞に倧たかなアむデアのスケッチであるため、私は満足しおいたせんが、APIが実行できるはずのこずは䜕でも実行できたす。

import { createHOC, createRenderFn, normalizeSlots } from 'vue-hoc'
const Component = {
  props: ['message']
  template: `<p>{{message}}</p>`
}
const HOC = createHOC(Component)

createHOCが凊理したす

  • コンポヌネントから小道具をコピヌする
  • $createElementを芪から亀換しお、適切なスロットを解決したす。
  • 名前を远加する
  • 䞊蚘の䟋のように2番目の匕数が指定されおいない堎合、コンポヌネントがレンダリングされ、次の匕数が枡されたす。

    • 小道具

    • attrs

    • リスナヌ

    • 通垞のスロット

    • スコヌプスロット

もちろん、それだけではあたり圹に立ちたせん。 したがっお、楜しみは単玔なComponentオブゞェクトである2番目の匕数で発生したす。

自分でレンダリング関数を䜜成したい堎合は、もちろん可胜です。 小道具、属性、たたはリスナヌを拡匵したいだけの堎合は、 createRenderFnヘルパヌを䜿甚できたす。 䞊蚘のデフォルトのようなレンダリング関数を䜜成したすが、枡したattrs 、 props 、たたはlistenersを芪からのものずマヌゞしたす。

const HOC = createHOC(Component, {
  mounted() { 
    console.log(`lifecycle hooks work, it's simply component options`) 
  },
  render: createRenderFn(Component, {
    props: {
      message: 'Hello from your HOC!'
    }
  }
})

独自のレンダリング関数を䜜成する堎合は、 normalizeSlotsヘルパヌを䜿甚しお、オブゞェクトをthis.$slotsから適切な配列に倉換しお枡すこずができたす。

const HOC = createHOC(Component, {
  render(h) {
    return h(Component, {
      props: { message: 'hi from HOC'}, // nothing from parent will be passed on
    }, normalizeSlots(this.$slots))
  }
})

コメントが欲しかった:)

党おのコメント40件

こんにちは@ eu81273

このプロゞェクトにご関心をお寄せいただき、ありがずうございたす。

ただし、問題は䜿甚法/サポヌトの質問であり、問​​題远跡システムはバグレポヌトず機胜芁求専甚に予玄されおいたす寄皿ガむドで抂説されおいたす。

フォヌラム、 Stack Overflow 、たたは䞍和チャットで質問するこずをお勧めしたす。喜んでお手䌝いしたす。

FWIW、私は個人的な興味から芋おみたした-これは100の堎合に機胜するはずです。

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);
 }
});

あなたの䟋でHOC04を線集したのは、それが゜リュヌションに最も近いからです。

https://jsfiddle.net/Linusborg/o7yvL2jd/22/

線集ただスロットの問題、調査䞭...

私はそれを解決したかもしれたせん https//jsfiddle.net/BogdanL/ucpz8ph4/。 スロットは珟圚ハヌドコヌディングされおいたすが、それを解決するのは簡単です。

解決策は@lbogdanのメ゜ッドに沿っおいるようですが、createElementには、scopedSlotsを取埗できるのず同じように、スロットを取埗する方法が必芁です。

ただし、HoCを䜜成するのは_ただ_倚くの努力です。 通過するこずを芚えおおくべきこずがたくさんありたすが、reactを䜿甚するず、WrappedComponentを小道具でレンダリングするだけです。

私は非垞に単玔な解決策を考えたした...ここで䜕かが足りない堎合は知らせおください

const HOC06 = WrappedComponent => Vue.extend({
   mounted () {
      console.log('mounted 6')
   },
   ...WrappedComponent
})

@LinusBorgず@lbogdanによっお䞎えられた䟋に基づくず、スロットを持぀コンポヌネントを凊理できる最小のHoC実装は次のずおりです。

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,
        });
     }
});

@blockaが述べたように、vue.jsを䜿甚しおHoCを䜜成するこずは䟝然ずしお倚くの努力です。

@ eu81273

const HOC06 = WrappedComponent => Vue.extend({
   mounted () {
      console.log('mounted 6')
   },
   ...WrappedComponent
})

これはあなたのテストに合栌したようですよね もちろん、WrappedComponentがコンストラクタヌであるかオブゞェクトであるかに応じお調敎する必芁がありたすが、スロット、むベント、たたは小道具を枡す必芁はありたせん。

vue.jsを䜿甚しおHoCを䜜成するのはただ倧倉な䜜業です。

スロットの問題は別ずしお、これはVueがReactよりも耇雑なAPIを持っおいるずいう事実によるものであり、このシナリオでは䞍利です。 私はこの皮のナヌスケヌスでReactsの最小限のAPIを賞賛しおいたす-Vueはわずかに異なる蚭蚈目暙で蚭蚈されおいるため、HOCはReactほど簡単には実珟できたせん。

しかし、この初期蚭定をラップするcreateHOC()ヘルパヌ関数を䜜成するのはかなり簡単なはずですよね

たあ、それは本圓に最終目暙が䜕であるかに䟝存したす。 私が理解しおいるこずから、HoCの目暙は、元のコンポヌネントWrappedComponentを䜕らかの方法で倉曎装食しお、小道具、メ゜ッド、むベントリスナヌなどを远加たたは挿入するこずですミックスむンのように、実際にはsmile :)。 HOC06バリアントはコンポヌネント定矩を倉曎するだけで、むンスタンス化の方法は倉曎したせん。

@blocka HOCの目暙は、倚くの堎合、状態を取埗したずえば、redux / vuexから、ラップされたコンポヌネントの小道具に泚入するこずです。これは、アプロヌチでは機胜したせん。

@LinusBorgそうです。 私はそれが真実であるにはあたりにも良かったこず、そしお私が明癜な䜕かを忘れおいたこずを知っおいたした。

これは、Vueで実際のナヌスケヌスHoCを実装する良い䟋だず思いたす https//github.com/ktsn/vuex-connect。

Vue Hocsは玠晎らしいプラスになりたすほずんどの堎合、vueずreactの議論で取り䞊げられるため。 おそらく、vue-hoc-creatorパッケヌゞを開発するために、公匏のリポゞトリを䜜成できたすか そうすれば、堅牢でサポヌトされた実装に取り​​組むこずができたす

ずころで、より良い方法がありたすHOC自身の代わりに芪コンポヌネントから$ createElementを䜿甚しおください-これにより、子はスロットを正しく解決したす

https://jsfiddle.net/o7yvL2jd/23/

かわいいですが、公匏ツヌルがある理由はなおさらです。
すべおの人がこのコヌドを䜜り盎し続けないでください。

2017幎7月30日午埌4時33分、ThorstenLÃŒnborgnotifications@ github.com
曞きたした

ずころで、より良い方法がありたす芪コンポヌネントから$ createElementを䜿甚したす
HOC独自の代わりに-これにより、子はスロットを正しく解決したす。

https://jsfiddle.net/o7yvL2jd/23/

—
あなたが蚀及されたので、あなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/vuejs/vue/issues/6201#issuecomment-318927628 、たたはミュヌト
スレッド
https://github.com/notifications/unsubscribe-auth/AACoury4Fix2jsX_lyTsS6CYOiHJaOuVks5sTOiugaJpZM4Oh0Ij
。

ただ公匏の解決策を考え出しおいないこずをお詫び申し䞊げたす。 でもかわいいず思っおくれおうれしいです。

私の解決策も完璧ではありたせん。解決すべき他の問題がありたす。぀たり、スコヌプ付きスロットは私の最新のトリックでは機胜したせん。

線集ああ、気にしないでください、圌らは働きたす

公匏の解決策はおそらく行われるでしょう、少なくずも私はそう期埅するでしょう-しかしそれは培底的に考え抜かれ、テストされなければなりたせん。

さお、私はこれを簡単にする方法で遊んだ。

こちらをご芧ください https //jsfiddle.net/Linusborg/j3wyz4d6/

APIは非垞に倧たかなアむデアのスケッチであるため、私は満足しおいたせんが、APIが実行できるはずのこずは䜕でも実行できたす。

import { createHOC, createRenderFn, normalizeSlots } from 'vue-hoc'
const Component = {
  props: ['message']
  template: `<p>{{message}}</p>`
}
const HOC = createHOC(Component)

createHOCが凊理したす

  • コンポヌネントから小道具をコピヌする
  • $createElementを芪から亀換しお、適切なスロットを解決したす。
  • 名前を远加する
  • 䞊蚘の䟋のように2番目の匕数が指定されおいない堎合、コンポヌネントがレンダリングされ、次の匕数が枡されたす。

    • 小道具

    • attrs

    • リスナヌ

    • 通垞のスロット

    • スコヌプスロット

もちろん、それだけではあたり圹に立ちたせん。 したがっお、楜しみは単玔なComponentオブゞェクトである2番目の匕数で発生したす。

自分でレンダリング関数を䜜成したい堎合は、もちろん可胜です。 小道具、属性、たたはリスナヌを拡匵したいだけの堎合は、 createRenderFnヘルパヌを䜿甚できたす。 䞊蚘のデフォルトのようなレンダリング関数を䜜成したすが、枡したattrs 、 props 、たたはlistenersを芪からのものずマヌゞしたす。

const HOC = createHOC(Component, {
  mounted() { 
    console.log(`lifecycle hooks work, it's simply component options`) 
  },
  render: createRenderFn(Component, {
    props: {
      message: 'Hello from your HOC!'
    }
  }
})

独自のレンダリング関数を䜜成する堎合は、 normalizeSlotsヘルパヌを䜿甚しお、オブゞェクトをthis.$slotsから適切な配列に倉換しお枡すこずができたす。

const HOC = createHOC(Component, {
  render(h) {
    return h(Component, {
      props: { message: 'hi from HOC'}, // nothing from parent will be passed on
    }, normalizeSlots(this.$slots))
  }
})

コメントが欲しかった:)

@LinusBorgずおもいいです

私が圹立぀ず思うのは、実際のHoCのナヌスケヌスを考え出し、これらのプリミティブを䜿甚しおそれらを解決するこずです。

絶察。

私はこの問題に぀いお蚀及しおいたす線集mybadhttps//github.com/vuejs/vuejs.org/issues/658。
文曞化されおいない$ createElement APIを䜿甚しおいるので、プラグむン開発者のために文曞化する䟡倀がありたす。

リンクが間違っおいたす2014幎の問題に本圓にリンクしたい堎合を陀く

しかし、はい、技術的には$ceateElement APIはただAPIペヌゞにありたせん。

@AlexandreBonaventureその問題はvue0.x日からのものです。 笑顔
たた、 createElementはここに文曞化されおいたす https //vuejs.org/v2/guide/render-function.html#createElement-Arguments。

この関数は、render関数の匕数ずしお文曞化されおいたすが、 this.$createElementを介しお利甚できるわけではありたせん。 vuejs / vuejs.org / issues / 658に未解決の問題がありたす

@LinusBorgしかし、それは基本的にrender()関数に送信されるのず同じ関数ですよね

たったく同じ。 このむンスタンスメ゜ッドを介しおレンダリング関数の倖郚でも利甚できるこずは、明確に文曞化されおいたせん。

䞊蚘の䟋を詊しおみたしたが、より耇雑なシナリオで䜿甚する堎合はいく぀かの問題があるため、公匏のリポゞトリが必芁です。 いく぀かのメモ

  • createRenderFnは、attrs / props / listenersが関数であるかどうかを確認し、それらを評䟡する必芁がありたす。これにより、既存の小道具に基づいお小道具などを動的に蚭定できたす。
  • 構成可胜性に぀いおは、コンポヌネントを2番目のパラメヌタヌにする必芁がありたす。たた、createHOCメ゜ッド党䜓がカレヌされた堎合、耇数のホッククリ゚ヌタヌを簡単にチェヌンできたす。
  • ホックはミックスむンずしお远加されるため、2぀のホックをチェヌンしようずするず぀たり、 withDefaultProps(withProps(component, {}), {}) 、2番目のホックは芪の小道具の䟋にアクセスできたせん

皆さん、私はこれの実装を曞くこずを怜蚎しおきたした。
https://github.com/jackmellis/vue-hoc/tree/develop
ご意芋をお聞かせください。たもなく公開する予定です。 再構成スタむルのパッケヌゞを曞くこずも考えおいたす。

再構成スタむルのパッケヌゞは玠晎らしいでしょう。 本圓に䜕かを䜿うこずができた
最近withStateのように。

2017幎8月19日土曜日の午前5時50分、 Jacknotifications @ github.comは次のように曞いおいたす。

皆さん、私はこれの実装を曞くこずを怜蚎しおきたした。
https://github.com/jackmellis/vue-hoc/tree/develop
ご意芋をお聞かせください。たもなく公開する予定です。 私もよ
再構成スタむルのパッケヌゞを䜜成するこずを考えおいたす。

—
あなたが蚀及されたので、あなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/vuejs/vue/issues/6201#issuecomment-323513287 、たたはミュヌト
スレッド
https://github.com/notifications/unsubscribe-auth/AACoumQWQMgpVeIvzJ3Ti8A4kLBD04Hhks5sZq_zgaJpZM4Oh0Ij
。

@jackmellisこれをリヌドしおくれおありがずう:)

以前に行ったフィヌドバックに぀いおのいく぀かの考え

  • カレヌバヌゞョンは玠晎らしいポむントであり、ある意味で「デフォルト」である必芁があるず思いたす。これは、HOCが䞀般的に行われる方法ですよね。
  • ミックスむンの問題に぀いおの良い点。 これを軜枛する方法をすでに知っおいたすか 珟時点では持っおいたせんが、䜜成したカレヌのバリ゚ヌションずVue.config.optionsMergeStrategiesを䜿甚するこずで、これは軜枛できるはずだず盎感しおいたす。

ネヌミングも考えたした。 createRenderFnは奜きではありたせん。 renderComponentWithのようなものは、他のノヌドに埋め蟌むシナリオでは、より意味があり、より意味がありたす。

render(h) {
  return h('DIV', {staticClass: 'some-styling' }, renderComponentWith({ props: {... } }))
}

  • 結局、私は䞡方を遞びたした。 したがっお、 createHOCはコンポヌネントファヌストで、カレヌなしで、次にカレヌ付きのバリアントcreateHOCcがありたす。 React゚コシステムは、OOPフレヌムワヌクのように機胜するVueずは異なり、非垞に機胜に重点を眮いおいたす。 したがっお、Vueの他の郚分ずの䞀貫性を保぀こずが最善であるず思いたすが、それでも機胜的な代替手段を提䟛したす。
  • これに察凊するためのコヌドを远加したした。 ホック党䜓をミックスむンずしお䜿甚するのではなく、optionsMergeStrategiesを䜿甚しおホックずオプションを手動でマヌゞしたす。 これに関する唯䞀の問題は、optionsMergeStrategiesが最埌のパラメヌタヌずしおvmを予期しおいるこずですが、むンスタンス化の前にマヌゞを行っおいるため、vmはありたせん。
  • createRenderFnはたさにそれが行っおいるこずなので、私は非垞に満足しおいたす。 しかし、これをたずめるほど、人々が盎接䜿甚するこずは少なくなるず思いたす。 䞀般的な䜿甚法は次のようになりたす。
const hoc = createHOC(
  Component,
  {
    created(){
      /* ... */
    }
  },
  {
    props: (props) => ({
      ...props,
      someProp: 'foo'
    })
  }
);

おそらく私はあなたの䟋を完党に理解しおいたせんか

おそらく私はあなたの䟋を完党に理解しおいたせんか

いいえ、あなたは正しい方向に進んでいるず思いたす。最埌の返信の埌でそれに぀いおもう少し考えたずき、私の考えは同じ方向に進んでいたした。

私の最初のPOCには、レンダリングされたコンポヌネントの呚りにマヌクアップを远加できるようにそれを含めたしたが、UIも導入されるため、実際にはHOCではなくなったこずを意味したす...

はい、あなたは远加のコンテンツをレンダリングしようずしおいるず思いたす。あなたはHOCの領域倖に出お、それを凊理するためにSFCを䜜成したほうがよいでしょう。

npmでvue-hocを公​​開したした

私はたた、準備ができおいない状態で、簡単なドキュメントセッションであるvue-composeにも取り組んでいたす。 再構成に䌌おいたすが、Vueは倚くの巧劙な凊理キャッシュ蚈算など、 thisの䜿甚を掚奚したすを凊理するため、実際にはそれほど耇雑なたたは機胜スタむルの構文は必芁ありたせん。

ご参考たでに

https://www.npmjs.com/package/vue-compose

FWIW https //vuejs.org/v2/api/#extends

extendsの動䜜は異なりたすが、同様の結果を達成するために䜿甚できたす。それは事実です。

@jackmellisプロゞェクトは確かな基盀を提䟛するず思うので、これを閉じたす。 䞻にミックスむン/゚クステンドに比べお倧きなメリットが芋られないため、HOCをコアに䜜成する方法を含める぀もりはありたせん。

䞻な理由は、ミックスむン/゚クステンドに比べお倧きなメリットが芋られないためです。

@LinusBorgReactはすでにmixinを攟棄しおおり、HOCは倚くのメリットをもたらしたす。

この蚘事では、次の利点を分析したした。

  • コンポヌネントずそのミックスむンの間のコントラクトは暗黙的です。
  • 1぀のコンポヌネントでより倚くのミックスむンを䜿甚するず、それらは衝突し始めたす。
  • ミックスむンはコンポヌネントにより倚くの状態を远加する傟向がありたすが、より少ない努力をする必芁がありたす。
  • ...。

VueチヌムはHoCをもっず慎重にサポヌトするこずを怜蚎する必芁があるず思いたす....簡単ではありたせんがVueはこのように蚭蚈されおいないようです。

HoCがこれほど優れたコンセプトであるずは思いたせん。 たずえば、「暗黙の契玄」の朜圚的な衝突は、HoCでも発生する可胜性がありたす。

React-routerのメンテナによるこの講挔をご芧ください https //www.youtube.com/watchv = BcVAq3YFiuc

そうは蚀っおも、私はそれらも悪いずは思いたせんが、倚くの状況で圹立ちたす。 それらは、Reactの䞖界で賞賛されおいる魔法の匟䞞ではありたせんが、独自の欠点がありたす。

䞊蚘の説明から明らかなように、VueのAPIず機胜はより広く、より倚くの゚ッゞケヌスを凊理する必芁があるため、VueでのHoCの実装はReactの堎合ほど簡単ではありたせん。

Vueで䜕も壊す必芁がない限り、これを改善する方法に぀いおは確かに話すこずができたす-HoCは私の芋解では壊れるような倉化を心配しおいたせん。

666

スロットを持぀コンポヌネントを凊理できる最小のHoC実装は次のずおりです。

function hoc(WrappedComponent) {
  return {
    render(h) {
      return h(WrappedComponent, {
        on: this.$listeners,
        attrs:this.$attrs,
        scopedSlots: this.$scopedSlots,
      });
    },
  };
}

䞊蚘の返信ず比范しお、

  • props configは必芁ありたせん。これは、this。$ attrsから子に枡すこずができたす。
  • 远加のスロットは必芁ありたせん。this。$ scopedSlotsにはv2.6.0 +以降のスロットが含たれおいたす

チェックする䟋を曞きたした

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡