Giter VIP home page Giter VIP logo

vue-proxi's Introduction

Proxi

<proxi> is a tiny proxy component. Whatever you add to it gets proxied to a target component!

πŸ™‹ Why?

  • ♻️ Uses Vue's Template API Doesn't re-invent component communication!
  • πŸ’ͺ Provide/Inject on Steroids! Familiar concepts, but super powered!
  • πŸ’₯ Reactive All injected data is reactive (unlike provide/inject)!
  • πŸ₯ Tiny 755 B Gzipped!

πŸš€ Install

npm i vue-proxi

🚦 3-step Setup

1. πŸ‘© Parent component

  • Import and register import Proxi from 'vue-proxi'
  • Insert anywhere in your template:
    • <proxi :proxi-key="key" [... attr / :prop / @listener]>
    • key is used to communicate with the Child. Use a unique string value or a Symbol

2. πŸ‘Ά Child component

  • Import the Proxi Inject mixin: import { ProxiInject } from 'vue-proxi'
  • Register the mixin:
export default {
    // ...,

    mixins: [
        ProxiInject({
            from: key, // from Step 1
            props: [
                // Becomes available on VM eg. `this.propName`
                'propName'
                // ...
            ]
        })
    ]
}

3. βœ… 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 }"

πŸ‘¨β€πŸ« 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).
πŸ‘© ParentπŸ‘Ά 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.
πŸ‘© ParentπŸ‘Ά 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 into v-bind
πŸ‘© ParentπŸ‘Ά 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!
πŸ‘© ParentπŸ‘Ά 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.

JSFiddle Demo

Usage
<template>
    <div>
        <radio-group v-model="selected">
            <radio
                label="Apples"
                value="apples"
            />
            <radio
                label="Oranges"
                value="oranges"
            />
            <radio
                label="Bananas"
                value="bananas"
            />
        </radio-group>
        <div>
            Selected: {{ selected }}
        </div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            selected: []
        }
    }
}
</script>
Parent: RadioGroup.vue
<template>
    <div>
        <proxi
            :proxi-key="key"
            :checked-items="value"
            @update="$emit('input', $event)"
        >
            <slot />
        </proxi>
    </div>
</template>

<script>
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'
        }
    }
}
</script>
Child: Radio.vue
<template>
    <label>
        <input
            type="checkbox"
            :checked="isChecked"
            @click="onClick"
        >
        {{ label }}
    </label>
</template>

<script>
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])
            }
        }
    }
}
</script>

πŸ‘ͺ Related

  • vue-subslot - πŸ’ Pick 'n choose what you want from a slot passed into your Vue component
  • vue-pseudo-window - πŸ–Ό Declaratively interface window/document in your Vue template
  • vue-vnode-syringe - 🧬Mutate your vNodes with vNode Syringe πŸ’‰

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.