vue-hybrids

1.1.3 • Public • Published

vue-hybrids

Hybrids web component wrappers for Vue components

npm version

vue-hybrids is an interop layer for Vue components and built on hybridsJS. Using vue-hybrids, you can quickly transition from building Vue single file components into pure web components with minimal interruptions to your toolchain.

Getting Started

Install npm package:

npm i --save-dev vue-hybrids

Then, import the vue-hybrids define function into your SFC:

<script>
import {define} from 'vue-hybrids'
 
export default define({
  name: 'my-vue-component',
  props: {
    foo: {type: String},
    bar: {type: Number},
  },
  // ...
})
</script> 

Finally, import the vue component to register it as a web component and use it in your appplication:

import './path/to/my-vue-component.vue'
<my-vue-component :foo="fooProp" :bar="barProp" @ondelete="onDelete" @onCreate="onCreate" />

define will wrap your component in a Hybrids JS web component, register it, and proxy all your props and events.

API

define

Define and register a new web component using an existing Vue component. Define returns the defn argument.

define(defnObject, optionsDefineOptions)void

defn

A Vue component definition. Some special considerations around various options:

  • name: This will be the name of the web component. By standard, web components must have a hyphen in their name.

options: DefineOptions

Various options for the component and/or component wrapper

  • vue?: Vue

    An instance of the Vue constructor. This can be helpful for components which need to inherit functionality from plugins.

    import {define} from 'vue-hybrids'
    import vue from 'vue'
    import Vuex from 'vuex'
    vue.use(Vuex)
     
    define({name: 'my-store', /* ... */}, {vue}) // the component has access to this.$store
  • styles?: string | string[]

    Style sheet strings for the shadowDOM. vue-hybrids will ensure that these styles do not bleed into the light DOM.

    import {define} from 'vue-hybrids'
    import globalStyles from './my-global-styles.styl'
    import styles from './my-styles.styl'
     
    define({name: 'my-styled-component', /* ... */}, {styles: [globalStyles, styles]})

If you are using the typical vue-loader toolchain to bundle styles in conjunction with vue-hybrids, SFC <style> tags will still be mounted in the light DOM and CSS selection into the shadow DOM will be restricted. Please avoid this in order to keep your web components side-effect free.

wrap

Wrap a vue component as a Hybrids component. The component can be defined later with a different name using the hybrids define function.

import {wrap} from 'vue-hybrids'
import {define} from 'hybrids'
 
const hybrid: Hybrids<CustomElement> = wrap(defnObject, optionsDefineOptions)
 
// ...
 
define('my-element-name', hybrid)

Attributes

These attributes are available on all vue-hybrids components

vh-debug

A boolean prop which is available for every vue-hybrid which renders the proxied props, their type, and their value.

<my-component :prop="foo" vh-debug/>

vh-key

A string key functioning much like key in Vue. If the value of vh-key changes, vue-hybrids will refresh the encapsulated Vue component. This will execute all of its lifecycle methods again.


Design Considerations

Binding Prop Data

When passing props to vue-hybrids components from a vue component, you will need to pass props by property instead of by attribute. To do this, add the .prop modifier to your props in vue templates.

  • An issue with the .prop shorthand (.) is documented here
<my-component :static="staticValue" :dynamic.prop="dynamicValue" />

Converting Vue Props

It's considered best practice to define types in your Vue component props. If no type is provided the wrapping hybrids component will assume a string, like other HTML attributes.

Vue Functionality

Avoid using the custom model property of Vue component definitions. When wrapped as a web component, the parent Vue component will not know to which event and prop it should bind v-model. Instead, design your component to use the traditional value prop and input event if possible. Or, if this is not possible, you may spell out the prop and event binding manually:

<my-component :value="myBoundValue" @change="(value) => myBoundValue = value" />

IE11

Though IE11 does not support the shadowDOM for style encapsulation, vue-hybrids should work with some polyfill support. Normally, one would include the following before any of their app code:

import '@webcomponents/webcomponentsjs`

However, if you are using @babel/preset-env and/or core-js, you may have difficulty with overlapping polyfills.

vue-hybrids provides a fix if your build falls into this scenario. Replace your @webcomponents import statement with:

import 'vue-hybrids/dist/polyfill.min.js' //464 KB

If your polyfill implementation is more complicated, a manual fix can be employed by assigning a nonsense Symbol before your @webcomponents import:

// Forces core-js to include their Symbol polyfill strictly before @webcomponents
const nonce = Symbol('I_DO_NOTHING')
import '@webcomponents/webcomponentsjs'

As a last resort, I've included a build of the @webcomponents/webcomponentsjs package which disincludes the Symbol polyfill. The package build outputs are generated from a fork (auzmartist/polyfills) and can be used like so:

import 'vue-hybrids/dist/legacy-polyfill.min.js' // 1,127 KB

Vue Dev Tools

vue-hybrids is compatible with vue dev tools. You can still inspect your mounted vue elements. Each defined component will show as wrapped in a <shadow-root> tag to signify it's placement in the shadow DOM.

NOTE: If using vue-hybrids within another Vue app, Vue Dev Tools will tend to bind to your app Vue instance.

Development

Contributions welcome!

git clone git@github.com:auzmartist/vue-hybrids.git
 
cd vue-hybrids
 
npm install
 
npm run dev

Package Sidebar

Install

npm i vue-hybrids

Weekly Downloads

217

Version

1.1.3

License

ISC

Unpacked Size

1.24 MB

Total Files

33

Last publish

Collaborators

  • auzmartist