In Vue.js, is there a way to keep component templates out of JavaScript strings?

Given that you are starting a new project, you can use vue-hackernews-2.0 as boilerplate, where you see lot of components already coded with webpack integration for both dev and prod env. This is also developed by core vue team and recommended in official docs.

You can see there are different files for each component and one component looks like following having clear separation of HTML, JS and CSS part:

<template>
  <li v-if="comment" class="comment">
    <div class="by">
      <router-link :to="'/user/' + comment.by">{{ comment.by }}</router-link>
      {{ comment.time | timeAgo }} ago
    </div>
    <div class="text" v-html="comment.text"></div>
    <div class="toggle" :class="{ open }" v-if="comment.kids && comment.kids.length">
      <a @click="open = !open">{{
        open
            ? '[-]'
            : '[+] ' + pluralize(comment.kids.length) + ' collapsed'
      }}</a>
    </div>
    <ul class="comment-children" v-show="open">
      <comment v-for="id in comment.kids" :id="id"></comment>
    </ul>
  </li>
</template>

<script>
export default {
  name: 'comment',
  props: ['id'],
  data () {
    return {
      open: true
    }
  },
  computed: {
    comment () {
      return this.$store.state.items[this.id]
    }
  },
  methods: {
    pluralize: n => n + (n === 1 ? ' reply' : ' replies')
  }
}
</script>

<style lang="stylus">
.comment-children
  .comment-children
    margin-left 1.5em
.comment
  border-top 1px solid #eee
  position relative
  .by, .text, .toggle
    font-size .9em
    margin 1em 0
  .by
    color #999
    a
      color #999
      text-decoration underline
  .text
    overflow-wrap break-word
    a:hover
      color #ff6600
    pre
      white-space pre-wrap
  .toggle
    background-color #fffbf2
    padding .3em .5em
    border-radius 4px
    a
      color #999
      cursor pointer
    &.open
      padding 0
      background-color transparent
      margin-bottom -0.5em
</style>

This uses webpack for build and adds working config as well which I myself am using in production without any issue.


You can use <template>...</template> or <script type="text/x-template">...</script>, and specify the selector in template attribute for that.

<template id="myComponent">
  <div>
    <h1>Hello!</h1>
    <p><slot></slot></p>
  </div>
</template>


Vue.component('myComponent', {
  template: '#myComponent'
})

Simple working example here: http://codepen.io/anon/pen/dNWrZG?editors=1010

Also, the build process of single file components is not that difficult. You can check the webpack-simple template: https://github.com/vuejs-templates/webpack-simple, the vue-loader will do everything for you.

Once you feel comfortable with webpack, you can take a look at the full webpack template: https://github.com/vuejs-templates/webpack