Vue.js HOC
by Jaeha Ahn
HTML
<script src="https://unpkg.com/[email protected]"></script>
<div id="demo">
<h3>baseComponent</h3>
<base-component foo="bar" @hello="hello" @click.native="native">
⑤ default-slot
<h4 slot="test">③ test-slot</h4>
</base-component>
<hr/>
<h3>HOC01</h3>
<enhanced-component1 foo="bar" @hello="hello" @click.native="native">
⑤ default-slot
<h4 slot="test">③ test-slot</h4>
</enhanced-component1>
<hr/>
<h3>HOC02</h3>
<enhanced-component2 foo="bar" @hello="hello" @click.native="native">
⑤ default-slot
<h4 slot="test">③ test-slot</h4>
</enhanced-component2>
<hr/>
<h3>HOC03</h3>
<enhanced-component3 foo="bar" @hello="hello" @click.native="native">
⑤ default-slot
<h4 slot="test">③ test-slot</h4>
</enhanced-component3>
<hr/>
<h3>HOC04</h3>
<enhanced-component4 foo="bar" @hello="hello" @click.native="native">
⑤ default-slot
<h4 slot="test">③ test-slot</h4>
</enhanced-component4>
<hr/>
<h3>HOC05</h3>
<enhanced-component5 foo="bar" @hello="hello" @click.native="native">
⑤ default-slot
<h4 slot="test">③ test-slot</h4>
</enhanced-component5>
</div>
CSS
#demo {
padding: 20px 80px 50px;
}
h3 {
color: red;
}
h4 {
background-color: yellow;
}
h5 {
background-color: #ff4200;
color: white;
}
p {
background-color: #00cc66;
}
code {
display: block;
background-color: #ff9933;
font-size: 15px;
}
hr {
background-color: transparent;
border: none;
height: 100px;
}
JavaScript
const BaseComponent = {
props: ['foo'],
template: `
<div>
<h5 @click="emitHello">① emit event (must be alert twice time)</h5>
<code>② props:{{JSON.stringify(this.$props)}}</code>
<slot name="test"></slot>
<p>④ between slots</p>
<slot></slot>
</div>
`,
methods: {
emitHello () {
this.$emit('hello');
}
}
}
const HOC01 = WrappedComponent => ({
render (h) {
return h(WrappedComponent, {props: this.$props});
}
});
const HOC02 = WrappedComponent => ({
props: WrappedComponent.props,
render (h) {
return h(WrappedComponent, { props: this.$props });
}
});
const HOC03 = WrappedComponent => ({
functional: true,
render (h, c) {
return h(WrappedComponent, c.data, c.children);
}
});
const HOC04 = WrappedComponent => ({
mounted () {
console.log('mouted!');
},
render (h) {
const slots = Object.keys(this.$slots).map(key => this.$slots[key]);
return h(WrappedComponent, {
attrs: this.$attrs,
listeners: this.$listeners,
}, slots);
}
});
const HOC05 = WrappedComponent => ({
template: `<wrapped v-on="$listeners" v-bind="$attrs"><slot/></wrapped>`,
components: {
'wrapped': WrappedComponent,
},
});
new Vue({
el: '#demo',
methods: {
hello () {
alert('Hello!!');
},
native () {
alert('Native!!');
}
},
components: {
BaseComponent,
EnhancedComponent1: HOC01(BaseComponent),
EnhancedComponent2: HOC02(BaseComponent),
EnhancedComponent3: HOC03(BaseComponent),
EnhancedComponent4: HOC04(BaseComponent),
EnhancedComponent5: HOC05(BaseComponent),
},
});