Vue 2.0 createHOC
HTML
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<h4>This is the Normal component rendered as-is:</h4>
<base-test
@update="alert($event)"
@click.native="handleNativeClick"
:message="message"
>
<p>This goes into the default slot</p>
<p slot="test">this goes into the test slot</p>
<template slot="withScope" scope="{message}">
<p>This is a scoped slot, it received the message: {{message}}</p>
</template>
</base-test>
<hr>
<h4>This is the same component wrapped in a HOC</h4>
<hoc
@update="alert($event)"
@click.native="handleNativeClick"
:message="message"
>
<p>This goes into the default slot</p>
<p slot="test">this goes into the test slot</p>
<template slot="withScope" scope="{message}">
<p>This is a scoped slot, it received the message: {{message}}</p>
</template>
</hoc>
<h4>
This is the same component with props
</h4>
<hoc2 :message="message"></hoc2>
<h4>
This component has a default message (overridden)
</h4>
<hoc3 :message="'bah'"></hoc3>
</div>
CSS
.default {
background-color: blue;
color: white;
}
.test {
background-color: green;
color: black;
}
.with-scope {
background-color: orange;
color: black;
}
Babel + JSX
const Component = {
name: 'Base',
template:
`<div>
<p>The message from the parent: {{message}}</p>
<button @click="$emit('update', 'hello! from the child!')">click me</button>
<a id="test-anchor" href="#" @click.prevent>Click me, for a native event!</a>
<div class="default"><slot/></div>
<div>something between the slots</div>
<div class="test"><slot name="test" /></div>
<div> And a scoped slot: </div>
<div class="with-scope"><slot name="withScope" :message="message" /></div>
</div>`,
props: ['message']
}
const HOC = createHOC(Component, {
created() {
console.log(`greetings from ${this.$options.name}`)
},
/*
* The `createRenderFn` helper create a render function that:
* - passes in all attrs, props and listeners that were defined on the component
* - merge those with any attrs, props and listeners passed to this function
* - normalize and pass on normal slots
* - pass on scoped slots
render: createRenderFn(Component, {
props: {
myProp: this.$store.getters('someGetter')
}
})
*/
/*
* If you want / have to create your own render function, you can use the
* `normalizeSlots` helper function to prepare slots to pass them:
render(h) {
return h(Component, {
// it's up to you what to pass on in the data object
// e.g. don't pass on attrs or props from the parent,
// and only pass on what you define in the HOC
}, normalizeSlots(this.$slots))
}
*/
})
const withProps = (component, props) => {
return createHOC(component, {
render: createRenderFn(component, {
props
}),
});
}
// this doesn't work
const withDefaultProps = (component, props) => {
return createHOC(component, {
render: createRenderFn(component, {
props: function(ownerProps){
const defaultProps = props.call(this, ownerProps);
const result = {};
Object.keys(defaultProps).forEach(key => {
if...