https://github.com/privatenumber/vue-proxi
π Tiny proxy component for Vue.js
https://github.com/privatenumber/vue-proxi
component inject parent-child provide proxy vue
Last synced: 7 months ago
JSON representation
π Tiny proxy component for Vue.js
- Host: GitHub
- URL: https://github.com/privatenumber/vue-proxi
- Owner: privatenumber
- License: mit
- Created: 2020-04-16T02:08:56.000Z (over 5 years ago)
- Default Branch: develop
- Last Pushed: 2023-05-18T05:28:47.000Z (over 2 years ago)
- Last Synced: 2025-03-09T13:22:39.374Z (7 months ago)
- Topics: component, inject, parent-child, provide, proxy, vue
- Language: JavaScript
- Homepage:
- Size: 381 KB
- Stars: 15
- Watchers: 3
- Forks: 3
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
`` is a tiny proxy component. Whatever you add to it gets proxied to a target component!
## :raising_hand: Why?
- :recycle: **Uses Vue's Template API** Doesn't re-invent component communication!
- :muscle: **Provide/Inject on Steroids!** Familiar concepts, but super powered!
- :boom: **Reactive** All injected data is reactive (unlike provide/inject)!
- :hatched_chick: **Tiny** 755 B Gzipped!## :rocket: Install
```sh
npm i vue-proxi
```## :vertical_traffic_light: 3-step Setup
#### 1. :woman: Parent component
- Import and register `import Proxi from 'vue-proxi'`
- Insert anywhere in your template:
- ``
- _`key` is used to communicate with the Child. Use a unique string value or a `Symbol`_
#### 2. :baby: Child component
- Import the Proxi Inject mixin: `import { ProxiInject } from 'vue-proxi'`
- Register the mixin:```js
export default {
// ...,mixins: [
ProxiInject({
from: key, // from Step 1
props: [
// Becomes available on VM eg. `this.propName`
'propName'
// ...
]
})
]
}
```
#### 3. :white_check_mark: Done!
- The injected data is all available in `this.$$`
- `this.$$.class`: Class
- `this.$$.props`: Props _(Automatically bound to VM)_
- `this.$$.attrs`: Attributes
- _eg. `v-bind="$$.attrs"` or `v-bind="{ ...$attrs, ...$$.attrs }"`_
- `this.$$.listeners`: Event listeners _(Automatically bound to VM)_
- _eg. `v-on="$$.listeners"` or `v-on="{ ...$listeners, ...$$.listeners }"`_## :man_teacher: Demos
Some quick demos to get you started!Inheriting props?
When you declare a prop, it filters it out from the attributes list ($$.attrs
) to be available directly on the view model (this.propName
) and the props list ($$.props
).
:woman: Parent:baby: Child
<proxi
:proxi-key="key"
:child-disabled="isDisabled"
:child-label="label"
/>
<label>
{{ label }}
<input
type="checkbox"
:disabled="childDisabled"
>
</label>
export default {
mixins: [
ProxiInject({
from: key,
props: [
'childDisabled',
'childLabel'
]
})
],
computed: {
label() {
return this.childLabel + ':';
}
}
};
Inheriting the class?
Both the static class and computed class are consolidated into$$.class
for you to easily attach to any element.
:woman: Parent:baby: Child
<proxi
:proxi-key="key"
class="static-class"
:class="['child-class', {
disabled: isDisabled
}]"
/>
<div :class="$$.class">
Child
</div>
export default {
mixins: [
ProxiInject({ from: key })
],
};
Inheriting attrs?
- Looking to inherit a specific attribute? Just pick it out from
$$.attrs
- Looking to inherit all attributes? Throw
$$.attrs
intov-bind
:woman: Parent:baby: Child
<proxi
:proxi-key="key"
:disabled="true"
/>
<div
:disabled="$$.attrs.disabled"
v-bind="$$.attrs"
>
Child
</div>
export default {
mixins: [
ProxiInject({ from: key })
],
};
Inheriting listeners?
All event listeners are in $$.listeners
to throw right into v-on
!
:woman: Parent:baby: Child
<proxi
:proxi-key="key"
@click="handleClick"
@custom-event="handleCustomEvent"
/>
<button v-on="$$.listeners">
Child
</button>
export default {
mixins: [
ProxiInject({ from: key })
],
mounted() {
// Listeners are automatically bound to VM
this.$emit('custom-event', 'Mounted!');
}
};
### Advanced
This demo shows how a parent-child pair, RadioGroup and Radio, communicate using Proxi. Note how the two components only come together at usage.
[](https://jsfiddle.net/hirokiosame/akwfm1sp/)
Usage
```vue
Selected: {{ selected }}
export default {
data() {
return {
selected: []
}
}
}
```
Parent: RadioGroup.vue
```vue
import Proxi from 'vue-proxi'
export default {
components: {
Proxi
},
props: ['value'],
data() {
return {
// Same idea as provide/inject
// Use a Symbol for security
key: 'radios'
}
}
}
```
Child: Radio.vue
```vue
{{ label }}
import { ProxiInject } from 'vue-proxi'
export default {
mixins: [
ProxiInject({
// Same key as parent
from: 'radios',
// Declare props that can be injected in
// Only array supported for now
props: ['checkedItems']
})
],
props: {
label: String,
value: null
},
computed: {
isChecked() {
return this.checkedItems.includes(this.value)
}
},
methods: {
onClick() {
if (this.isChecked) {
this.$emit('update', this.checkedItems.filter(i => i !== this.value))
} else {
this.$emit('update', [...this.checkedItems, this.value])
}
}
}
}
```
## :family: Related
- [vue-subslot](https://github.com/privatenumber/vue-subslot) - π Pick 'n choose what you want from a slot passed into your Vue component
- [vue-pseudo-window](https://github.com/privatenumber/vue-pseudo-window) - πΌ Declaratively interface window/document in your Vue template
- [vue-vnode-syringe](https://github.com/privatenumber/vue-vnode-syringe) - π§¬Mutate your vNodes with vNode Syringe π