透過Vue CLI實做Web Component

2021/01/07

Web Component

通常在Web開發上

常用的功能都是以各種套件達到reuse的效果

不過有時候使用套件的時候會遇到

套件的HTML/CSS/JS影響到原本網站的樣式或是互相影響的問題

 

但Web Component不會

因為Web Component是使用Shadow DOM

因此Web Component內部可以完全獨立運作HTML/CSS/JS與外部完全隔離

 

相容性

https://developer.mozilla.org/en-US/docs/Web/Web_Components#Browser_compatibility

基本上主流瀏覽器像是Chrome、Firefox都完全支援

如果專案是可以限制使用者瀏覽器的話

基本上就沒問題

真的不支援的瀏覽器

也可以透過Web Component的polyfill來處理

 

Vue CLI Build Web Component

Vue CLI其實到3.x版已經很方便了(官方文件)

可以將某個Vue元件直接打出Web Component

什麼polyfill的都不用管

打包完還直接給一個範例的html

 

如何在外部使用Web Component

這邊直接使用Vue CLI打出來的demo.html

其實就載入Vue.js、Web component的js

然後把Web Component的custom element放到html內就可以了

<meta charset="utf-8">
<title>demo-component demo</title>
<script src="https://unpkg.com/vue"></script>
<script src="./demo-component.js"></script>


<demo-component></demo-component>

 

外部如何與Web Component溝通

方法很多

不過我個人覺的使用JavaScript Custom Event最簡單方便

 

JavaScript Custom Event

透過原生JS Event讓Web Component與外部互相丟Event溝通或傳資料

// 建立並發送FOOBAR event
const event = new CustomEvent('FOOBAR', {
  detail: { foo: 'bar' },
})
window.dispatchEvent(event)

// 監聽FOOBAR event
window.addEventListener('FOOBAR', (event) => {
  const payload = event.detail // event參數
  console.log(payload.foo) // bar
})

 

Web Component中使用Vuex

vuex很好用

Vue CLI打出來的專案vuex的store都是在main.js中設定

如果是在Web Component Vue內要使用vuex的話

其實就跟在main.js中的作法一樣

載入store.js裝到vue instance內即可

<script lang="babel" type="text/babel">
import store from 'store/index.js'
export default {
  store,
}
</script>

 

Web Component中使用Vuetify

Vuetify算是我很常用的Vue Framework

Vuetify有很多方便的css helper或是元件可以使用

如果Web Component可以使用的話開發會更方便快速

 

Web Component Vue根元件中

如果只要使用某幾個元件

可以參考Vuetify的Tree Shaking文件用法

只載入要使用的元件即可

<template>
  <v-app>
    <v-main>
      This is web component
    </v-main>
  </v-app>
</template>

<script lang="babel" type="text/babel">
import Vue from 'vue'
import { VApp, VMain, VBtn, VImg, VRow } from 'vuetify/lib'
Vue.component('v-app', VApp)
Vue.component('v-main', VMain)
Vue.component('v-btn', VBtn)
Vue.component('v-row', VRow)
Vue.component('v-img', VImg)

import vuetify from 'plugins/vuetify'
export default {
  vuetify,
}
</script>

<style src="vuetify/dist/vuetify.min.css"></style>

 

其他

Web Component範例(包含Vuetify):https://github.com/ciao-chung/web-component-demo