Компоненты бесполезны, если они представляют собой жестко запрограммированные образцы кода копирования / вставки, вставленные по всей странице. Их сила заключается в том, чтобы сделать их гибкими.

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

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Simple Dynamic Components</title>
</head>
<body>

<div id="app">
    <toggle-component></toggle-component>
    <toggle-component></toggle-component>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>
<script src='app.js'></script>
</body>
</html>

и файл app.js:

// app.js
Vue.component('toggle-component', {
    template: "<div>
          <button @click='toggle()'>Open/Close</button>
          <span v-show=\"isOpen\">Toggle info</span>
        </div>",
    data: function () {
        return {
            isOpen: false
        }
    },
    methods:{
        toggle: function(){
            this.isOpen = !this.isOpen
        }
    }
});

new Vue({
    el: '#app',
});

У вас есть два экземпляра вашего `toggle-component`, но оба они имеют одно и то же жестко запрограммированное содержимое (« Toggle info »). Вы же не хотите, чтобы все ваши компоненты говорили об этом! Исправьте это.

Где вы сделаете это изменение? Если вы посмотрите на свое определение «Vue.component», то поймете, что это одно и то же для обоих экземпляров «toggle-component», так что это должно быть похоже на вашу функцию. Каждый раз, когда он вызывается, он выполняет какие-то действия и отображает на странице определенный HTML-код. Таким образом, очевидно, что вы хотите передать контент из извне компонента . Затем вы запишите его и передадите в шаблон для рендеринга. Хорошо - концепция опущена, давайте сделаем это на практике!

В своем шаблоне замените жестко запрограммированную строку переменной с именем «content». Обратите внимание на {{}}, чтобы удерживать его:

template: "<div><button @click='toggle()'>Open/Close</button>" +
"<span v-show=\"isOpen\">{{ content }}</span>" +
"</div>",

Большой! Теперь о компонентах, сообщите ему значение, которое нужно передать:

<toggle-component content="Top one"></toggle-component>
<toggle-component content="Bottom one"></toggle-component>

Теперь обновите свою страницу и… подождите! Просто пусто. Нет ошибки. Нет, ничего…

Проблема в том, что вы не можете просто передать данные извне напрямую в свой шаблон. Вместо этого используйте что-то под названием реквизиты. Реквизиты используются всякий раз, когда вы хотите передать что-то в дочернему элементу. В этом случае подумайте об элементах «toggle-component» как о «внешних» слоях, передающих содержимое в свои внутренние органы. Может быть, это только сбивало с толку. Извините.

Прямо над шаблоном добавьте свой реквизит:

props: ['content'],

Почему это называется «реквизит»? Я считаю, что это сокращение от «свойства». Все фронтенд-разработчики втайне завидуют тому, что они слишком молоды, чтобы использовать венгерскую нотацию, и пытаются это исправить (но делают это неправильно). В любом случае, это касательная…

Хорошо! У вас есть динамический контент в ваших компонентах! Теперь я знаю, о чем вы думаете: «Джефф, мне бы очень хотелось знать, сколько раз нажимается каждая из этих кнопок». Конечно бы. А кто бы не стал?

Подумайте, как вы это сделаете. У вас уже есть функция onClick, toggle (), так что это хорошее место для увеличения счетчика.

methods:{
    toggle: function(){
        this.isOpen = !this.isOpen;
        this.clicked += 1;
    }
}

Отобразите его как часть строки, которая показывает, когда диапазон открывается, например:

template: "<div>
      <button @click='toggle()'>Open/Close</button>  
      <span v-show=\"isOpen\">{{ content }} clicked {{ clicked }} times.</span>
    </div>",

Большой! Обновите страницу и… белый. Пустой. Ничего такого.

Что вам не хватает? Ах! Вы еще нигде не определили "нажал". Нет проблем - просто имитируйте то, что вы сделали для «контента»:

<toggle-component content="Top one" clicked="0"></toggle-component>
<toggle-component content="Bottom one" clicked="0"></toggle-component>

и в вашем реквизите:

props: ['content', 'clicked'],

Обновите, переключите кнопку, и… он останется на 0. Хмммм….

Вы, вероятно, кричите перед компьютером: «Не так, ты # $% &!» но сначала для меня это было не так очевидно. Что вы делаете с этим способом настройки, - это всегда каждый раз передавать 0 в шаблон. Вы не хотите этого делать - вместо этого вы хотите внутренне работать с "нажатыми".

Удалите из реквизита "нажатие" и вместо этого используйте:

data: function () {
    return {
        isOpen: false,
        clicked: 0
    }
},

Это инициализирует переменную clicked и устанавливает ее в 0 для начала. Вот почему в вашей функции toggle () вы называете ее this .clicked, и она работает так же, как и другая ваша переменная isOpen. Теперь, когда вы нажимаете, он увеличивается, каждая кнопка отдельно.

Конечно, все станет сложнее, но я думаю, что если вы немного поиграете с этим кодом и убедитесь, что понимаете разницу, это очень поможет вам понять Vue.js.

Последнее, на что следует обратить внимание - вы видите, что забыли удалить свой атрибут «clicked»:

<toggle-component content="Top one" clicked="0"></toggle-component>
<toggle-component content="Bottom one" clicked="0"></toggle-component>

и все же все еще работает? Это то, что может сделать ошибки очень трудно отладить; по сути, вы просто передаете значение и игнорируете его, поэтому все по-прежнему работает, но ничего не делает. Не позволяйте этому зацепить вас!

Надеюсь, это поможет! С радостью отвечу на вопросы и благодарен за рекомендации и твиты, если вы думаете, что это поможет другим!