Статьи

7 способов определить шаблон компонента в Vue.js

Существует множество вариантов определения шаблонов компонентов в Vue. По моим подсчетам есть как минимум семь разных способов:

  • строка
  • Шаблон буквальный
  • X-шаблоны
  • В линию
  • Рендеринг функций
  • JSX
  • Одностраничные компоненты

А может и больше!

В этой статье мы рассмотрим примеры каждого из них и рассмотрим плюсы и минусы, чтобы вы знали, какой из них лучше всего использовать в любой конкретной ситуации.

1. Струны

По умолчанию шаблон будет определен как строка в вашем файле JS. Я думаю, что мы все можем согласиться с тем, что шаблоны в строке довольно непонятны. Этот метод не имеет большого значения, кроме широкой поддержки браузера.

Vue.component('my-checkbox', {
    template: `<div class="checkbox-wrapper" @click="check"><div :class="{ checkbox: true, checked: checked }"></div><div class="title">{{ title }}</div></div>`,
    data() {
        return { checked: false, title: 'Check me' }
    },
    methods: {
        check() { this.checked = !this.checked; }
    }
});

2. Шаблонные литералы

Шаблонные литералы ES6 («backticks») позволяют вам определять ваш шаблон в нескольких строках, чего вы не можете сделать в обычной строке JavaScript. Их гораздо проще читать, и теперь они поддерживаются во многих новых браузерах, хотя вам, вероятно, все равно придется перейти на ES5, чтобы быть в безопасности.

Однако этот метод не идеален; Я обнаружил, что большинство IDE все еще доставляют вам горе с подсветкой синтаксиса, и форматирование вкладок, новых строк и т. Д. Все еще может быть проблемой.

Vue.component('my-checkbox', {
    template: `<div class="checkbox-wrapper" @click="check">
                            <div :class="{ checkbox: true, checked: checked }"></div>
                            <div class="title">{{ title }}</div>
                        </div>`,
    data() {
        return { checked: false, title: 'Check me' }
    },
    methods: {
        check() { this.checked = !this.checked; }
    }
});

3. X-шаблоны

С помощью этого метода ваш шаблон определяется внутри тега script в файле index.html . Тег сценария помечен text/x-templateи обозначен идентификатором в определении вашего компонента.

Мне нравится, что этот метод позволяет вам писать HTML в правильной разметке HTML, но недостатком является то, что он отделяет шаблон от остальной части определения компонента.

Vue.component('my-checkbox', {
    template: '#checkbox-template',
    data() {
        return { checked: false, title: 'Check me' }
    },
    methods: {
        check() { this.checked = !this.checked; }
    }
});
<script type="text/x-template" id="checkbox-template">
    <div class="checkbox-wrapper" @click="check">
        <div :class="{ checkbox: true, checked: checked }"></div>
        <div class="title">{{ title }}</div>
    </div>
</script>

4. Встроенные шаблоны

Добавляя inline-templateатрибут к компоненту, вы указываете Vue, что внутреннее содержимое является его шаблоном, а не рассматриваете его как распределенное содержимое (см. Слоты ).

Он имеет тот же недостаток, что и x-шаблоны, но одним из преимуществ является то, что содержимое находится в правильном месте в шаблоне HTML и поэтому может отображаться при загрузке страницы, а не в ожидании запуска JavaScript.

Vue.component('my-checkbox', {
    data() {
        return { checked: false, title: 'Check me' }
    },
    methods: {
        check() { this.checked = !this.checked; }
    }
});
<my-checkbox inline-template>
    <div class="checkbox-wrapper" @click="check">
        <div :class="{ checkbox: true, checked: checked }"></div>
        <div class="title">{{ title }}</div>
    </div>
</my-checkbox>

5. Функции рендеринга

Функции рендеринга требуют, чтобы вы определили свой шаблон как объект JavaScript. Они явно самые многословные и абстрактные из вариантов шаблона.

Однако преимущества в том, что ваш шаблон ближе к компилятору и дает вам доступ ко всем функциям JavaScript, а не к подмножеству, предлагаемому директивами.

Vue.component('my-checkbox', {
    data() {
        return { checked: false, title: 'Check me' }
    },
    methods: {
        check() { this.checked = !this.checked; }
    },
    render(createElement) {
        return createElement(
            'div',
            {
                    attrs: {
                        'class': 'checkbox-wrapper'
                    },
                    on: {
                        click: this.check
                    }
            },
            [
                createElement(
                'div',
                {
                    'class': {
                        checkbox: true,
                        checked: this.checked
                    }
                }
                ),
                createElement(
                'div',
                {
                    attrs: {
                    'class': 'title'
                    }
                },
                [ this.title ]
                )
            ]
        );
    }
});

6. JSX

Самым спорным вариантом шаблона в Vue является JSX. Некоторые разработчики считают JSX уродливым, неинтуитивным и предательством Vue.

JSX требует, чтобы вы сначала перенесли его, так как он не читается браузерами. Но если вам нужно использовать функции рендеринга, JSX, безусловно, является менее абстрактным способом определения шаблона.

Vue.component('my-checkbox', {
    data() {
        return { checked: false, title: 'Check me' }
    },
    methods: {
        check() { this.checked = !this.checked; }
    },
    render() {
        return <div class="checkbox-wrapper" onClick={ this.check }>
                 <div class={{ checkbox: true, checked: this.checked }}></div>
                 <div class="title">{ this.title }</div>
               </div>
    }
});

7. Отдельные файловые компоненты

So long as you are comfortable with using a build tool in your setup, Single File Components are the king of template options. They bring the best of both worlds: allowing you to write markup while keeping all your component definitions in one file.

They require transpiling and some IDEs don’t support syntax highlighting for this file type — but they are otherwise hard to beat.

<template>
  <div class="checkbox-wrapper" @click="check">
    <div :class="{ checkbox: true, checked: checked }"></div>
    <div class="title">{{ title }}</div>
  </div>
</template>
<script>
  export default {
    data() {
      return { checked: false, title: 'Check me' }
    },
    methods: {
      check() { this.checked = !this.checked; }
    }
  }
</script>

You might argue there are even more template definition possibilities since you can use template pre-processors like Pug with SFCs!

Which Is the Best?

Of course, there’s no one perfect way, and each should be judged on the use case you have. I think the best developers will be aware of all the possibilities and have each as a tool in their Vue.js toolbelt!