# Web Components and Framework Integration Vue & React Case Study

For a long time, I dreamed of building a fully customizable, reusable, and cross-framework UI component library to streamline my project development. By chance, I discovered Web Components, a native Web API that allows the creation of custom HTML tags for component-based development. Excited by its potential, I decided to integrate Web Components with popular frontend frameworks—React and Vue—in my latest project to explore the possibilities of this combination.

Early in the project, I was captivated by the power of Web Components. Supported natively by browsers, they require no external libraries or frameworks and offer full encapsulation, enabling components to be used independently anywhere.

## Web Components Integration with Vue

Integrating Web Components with Vue.js typically involves creating and using custom elements within a Vue application while preserving Vue’s data binding and lifecycle methods.

### Installing @vue/web-component-wrapper

```bash
npm install --save @vue/web-component-wrapper
```

Suppose we have a Vue component named `MyVueComponent.vue`:

### MyVueComponent.vue

```html
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello from Vue Component'
    };
  },
  methods: {
    increment() {
      this.message = 'Count incremented!';
    }
  }
};
</script>
```

Next, we can use `@vue/web-component-wrapper` to convert this Vue component into a Web Component:

### index.js

```javascript
import Vue from 'vue';
import MyVueComponent from './MyVueComponent.vue';
import VueWebComponentWrapper from '@vue/web-component-wrapper';

Vue.customElement('my-vue-component', MyVueComponent);

// Alternatively, if you want to use LitElement as a base:
// import { LitElement, html } from 'lit-element';
// import { wrap } from '@vue/web-component-wrapper';
// import MyVueComponent from './MyVueComponent.vue';

// class MyCustomElement extends LitElement {
//   render() {
//     return html`
//       <my-vue-component></my-vue-component>
//     `;
//   }
// }

// wrap(Vue, MyCustomElement, MyVueComponent);

customElements.define('my-vue-component', VueWebComponentWrapper(MyVueComponent));
```

Now, you can use the `<my-vue-component>` tag anywhere Web Components are supported, like this:

### index.html

```html
<!DOCTYPE html>
<html>
<head>
  <title>Vue Web Component</title>
</head>
<body>
  <my-vue-component></my-vue-component>
  <script src="index.js"></script>
</body>
</html>
```

The Vue component `MyVueComponent` is transformed into a Web Component, retaining its internal data binding and methods. In an external HTML file, you can use the `<my-vue-component>` tag without importing the entire Vue library.

### Vue Page (App.vue)

```html
<template>
  <div>
    <my-vue-component></my-vue-component>
  </div>
</template>

<script>
export default {
  name: 'App'
};
</script>
```

## Web Components Integration with React

Web Components can be used directly in React applications since they are natively supported by browsers, independent of specific frameworks.

### Web Component (MyCustomElement.js)

```javascript
import { LitElement, html, css } from 'lit-element';

class MyCustomElement extends LitElement {
  static get styles() {
    return css`
      /* Custom styles */
    `;
  }

  static get properties() {
    return {
      someProp: { type: String },
    };
  }

  constructor() {
    super();
    this.someProp = 'Default value';
  }

  _handleClick() {
    this.dispatchEvent(new CustomEvent('custom-event', { detail: 'Hello from LitElement' }));
  }

  render() {
    return html`
      <button @click="${this._handleClick}">Click me</button>
      <p>${this.someProp}</p>
    `;
  }
}

customElements.define('my-custom-element', MyCustomElement);
```

### React Component (App.js)

```jsx
import React from 'react';

function App() {
  const handleCustomEvent = (event) => {
    console.log('Custom event received:', event.detail);
  };

  return (
    <div>
      <my-custom-element some-prop="React Value" on-custom-event={handleCustomEvent}></my-custom-element>
    </div>
  );
}

export default App;
```

### Key Considerations for Using Web Components in React

* **Property Binding**: React uses camelCase for properties, while Web Components use kebab-case. In React, use `some-prop` instead of `someProp` for attribute binding.
    
* **Event Listening**: React’s JSX `@event` syntax doesn’t directly map to Web Component event listeners. React attaches event listeners to the outermost DOM element, so `@custom-event` listens on the React component’s root, not directly on the Web Component. If the Web Component’s events don’t bubble, handle them within the Web Component itself.
    
* **State Management and Updates**: React’s state management and component update mechanisms differ from Web Components. Web Component state changes won’t trigger React re-renders.
    
* **Lifecycle Methods**: React’s lifecycle methods don’t fully align with Web Components’ lifecycles. Coordination may be needed for operations tied to specific lifecycle stages.
    
* **Performance Considerations**: Since React doesn’t directly manage Web Components, additional optimizations like `shouldComponentUpdate` or `React.memo` may be required to minimize unnecessary renders.
