UNPKG

6.09 kBMarkdownView Raw
1# vue-hoc
2Create Higher Order Vue Components
3
4Inspired by https://github.com/vuejs/vue/issues/6201
5
6## Installation
7```
8npm install --save vue-hoc
9```
10
11## Usage
12The simplest way to create a Higher Order Component is with the `createHOC` method. It takes a base component, a set of component options to apply to the HOC, and a set of *data* properties to pass to the component during render.
13```js
14import { createHOC } from 'vue-hoc';
15import MyComponent from '../my-component';
16
17const options = {
18 name: 'MyEnhancedComponent',
19 computed: {
20 myComputedProperty(){
21 return this.someProp + ' computed';
22 }
23 },
24 created(){
25 console.log('Created')
26 }
27};
28
29const renderWith = {
30 props: {
31 someProp(){
32 return this.myComputedProperty;
33 }
34 },
35 listeners: {
36 someEvent(arg){
37 this.$emit('someOtherEvent', arg);
38 }
39 }
40};
41
42const enhanced = createHOC(MyComponent, options, renderWith);
43```
44The resulting HOC component will render the base component, but will pass in the value of `myComputedProperty` in place of `someProp`.
45
46The alt method `createHOCc` exposes a curried version of the same method, where the component is the last argument, allowing you to write *HOC creators* and potentially chain up multiple hocs:
47```js
48import { createHOCc } from 'vue-hoc';
49import { compose } from 'ramda';
50import MyComponent from '../my-component';
51
52const withCreatedHook = createHOCc({
53 created(){
54 console.log('Created');
55 }
56}, null);
57
58const withAmendedProp = createHOCc(null, {
59 props: {
60 someProp(){
61 return this.someProp + ' amended';
62 }
63 }
64});
65
66// we can now create a HOC using these methods
67const MyComponent2 = withCreatedHook(MyComponent);
68
69// and we can do multiple hocs:
70const MyComponent3 = withAmendedProp(withCreatedHook(MyComponent));
71
72// and with a composer like ramda's compose, we can make it more readable:
73const enhance = compose(
74 withAmendedProp,
75 withCreatedHook
76);
77const MyComponent4 = enhance(MyComponent);
78```
79
80## API
81### createHOC
82```js
83(Component: Object | Function, options?: Object, renderWith?: Object) => Object;
84```
85Wraps a component in a higher order component. Any props, listeners, and attributes will be passed through the HOC into the original Component.
86```js
87const hocComponent = createHOC(Component);
88```
89
90#### options
91The options object will be used as the HOC's component definition. Here you can pass any valid [component definition options](https://vuejs.org/v2/api/#Options-Data).
92```js
93const withCreatedHook = createHOC(Component, {
94 created(){
95 console.log(this.someProp);
96 // Where some prop is a prop defined on the original component.
97 // The HOC will have access to it and it will still be passed on to the original component.
98 }
99});
100```
101**vue-hoc** will automatically inherit the base component's props so you can access these from within the hoc and they will be passed into the base component during the render. If you set a new value for props, it will be merged with the inherited props using Vue's [option merging strategies](https://vuejs.org/v2/api/#optionMergeStrategies).
102```js
103createHOC(Component, {
104 props: ['someAdditionalProp']
105});
106```
107
108**vue-hoc** will also automatically create a render function for the HOC, but you can override this by setting a `render` function yourself. Keep in mind, however, that a custom render function will no longer handle the `renderWith` options.
109```js
110createHOC(Component, {
111 render(h){
112 /* ... */
113 }
114});
115```
116
117#### renderWith
118The renderWith object allows you to amend what props, listeners and attributes will be passed into the child component. In actuality, you can pass in any property that is accepted by Vue's [createElement](https://vuejs.org/v2/guide/render-function.html#The-Data-Object-In-Depth) method.
119
120>The exception is that the `on` property is renamed to `listeners`.
121
122Each option can be one of the following formats:
123```js
124{
125 [name: string]: any
126}
127```
128This will just pass static properties into the component instance. i.e.
129```js
130createHOC(Component, null, {
131 props: {
132 staticProp: 'foo',
133 otherStaticProp: [1, 2, 3]
134 }
135});
136```
137The properties will be merged into the existing properties.
138
139```js
140{
141 [name: string]: (owner: Object) => any
142}
143```
144This allows you to calculate specific properties individually. You can also include static properties alongisde this. i.e.
145```js
146createHOC(Component, null, {
147 props: {
148 dynamicProp(props){
149 return props.someProp + ' dynamic';
150 },
151 otherDynamicProp(){
152 return this.someOtherProp + ' dynamic';
153 },
154 staticProp: 'foo'
155 }
156});
157```
158The properties will be merged into the existing properties.
159
160Keep in mind that `listeners`, `nativeOn`, and `scopedSlots` are meant to be functions so they will not be evaluated.
161
162```js
163(owner: Object) => any
164```
165This allows to return the entire property object. i.e.
166```js
167createHOC(Component, null, {
168 props(props){
169 return {
170 ...props,
171 dynamicProp: 'dynamic'
172 };
173 }
174});
175```
176Unlike the previous variants, this will *not* automatically merge with the existing properties.
177
178### createHOCc
179```js
180(options: Object, renderWith: Object, Component: Object | Function) => Object;
181```
182This is a curried variation of the `createHOC` method. This allows you to build a HOC creator and pass in a component at the end.
183
184### createRenderFn
185```js
186(Component: Object, renderWith?: Object)=> Function;
187```
188createRenderFn is responsible for rendering the wrapped component in your hoc.
189```js
190const hoc = createHOC(Component, {
191 render: createRenderFn(Component, {})
192});
193```
194It is already used by `createHOC` to generate the render property of the component so you do not need to pass it in every time.
195
196#### options
197See [renderWith](#renderwith).
198
199### createRenderFnc
200```js
201(options: Object, Component: Object)=> Function;
202```
203A curried version of `createRenderFn`.
204
205### normalizeSlots
206```js
207(slots: Object) => Array<Object>;
208```
209A simple method that takes a component's slots and converts them into an array. This is used to pass distributed content from a parent to a child component during the render.