🔥

【Vue】webpack(等のバンドラ)が使えないときの x-template【CodePenとかに使える】

2021/06/22に公開

x-template とは

https://jp.vuejs.org/v2/guide/components-edge-cases.html#X-テンプレート

テンプレートを定義する別の方法は、type 属性text/x-templateを用いたスクリプト要素の内部で定義することです。そのとき、id によってテンプレートを参照する必要があります。

what?

webpackとかがなくてSFCが使えないときのVueの書き方は一般的にこんな感じ

main.js
const App = {
  template: `
    <div>
      Hello World!
    </div>
  `
}

Vue.createApp(App).mount("#app");

わかる

これを、こんな感じにできる

index.html
<body>
  <div id="app" />
</body>

<script id="component" type="text/x-template">
  <div>Hello World!</div>
</script>
main.js

const App = {
  template: "#component" // x-template を探すセレクタを書く
}

Vue.createApp(App).mount("#app");

つまり、 template をHTMLとして書くことができる

何がうれしいの?

上述の例だとコードがシンプルすぎて分かりづらいが、コンポーネントを持つVueアプリケーションをバンドラなしで作りたいときに便利だと思う。
CodePenみたいな環境でSFCっぽいものを再現できるし。

例っぽいもの

index.html
<body>
  <div id="app">
    <Parent />
  </div>
</body>

<script id="Parent" type="text/x-template">
  <div>
    <Child @from-child="emitFromChild" />
    <input type="text" v-model="parentText" />
  </div>
</script>

<script id="Child" type="text/x-template">
  <div>
    parent
    <button @click="emitFromChild">Emit!</button>
    <p>{{ text }}</p>
  </div>
</script>
main.js
const Child = {
  template: "#Child",
  data() {
    return {
      text: ""
    };
  },
  methods: {
    emitFromChild() {
      this.$emit("fromChild", { fireFromParent: this.fireFromParent });
    },
    // このメソッドは子コンポーネントのスコープを持っている
    fireFromParent(text) {
      console.log("I'm Child");
      this.text = text;
    }
  }
};

const Parent = {
  template: "#Parent",
  components: {
    Child
  },
  data() {
    return {
      parentText: "from Parent !"
    };
  },
  methods: {
    emitFromChild(obj) {
      console.log("I'm Parent");
      obj.fireFromParent(this.parentText);
    }
  }
};

const App = {
  components: {
    Parent
  }
};

Vue.createApp(App).mount("#app");

https://codepen.io/fruitriin/pen/wvJbBXm?editors=0001

Discussion