Как сохранить мои данные в пользовательском компоненте Vue вместо корневого экземпляра Vue? - PullRequest
1 голос
/ 29 мая 2019

Я создаю собственный компонент-флажок в Vue, и он отлично работает с данными, хранящимися в корневом экземпляре.Я планирую повторно использовать этот компонент (наряду со многими другими компонентами, которые я создаю) в самых разных случаях.Я не хочу обновлять или редактировать корневой экземпляр Vue каждый раз, когда я использую компонент, и хочу хранить данные ТОЛЬКО в самом компоненте.Логическое значение check / unchecked должно быть реактивным.

Я поэкспериментировал с использованием вычисленного значения, но не смог заставить его работать.Я открыт для использования этого, хотя, если мне нужно.

(ЭТА ВЕРСИЯ НЕ РАБОТАЕТ)

<body>
  <script src="https://unpkg.com/vue@2.6.10"></script>
  <div id="app">
    <checkbox-item v-model="checkData">Active</checkbox-item>
    {{ checkData }}
  </div>
</body>

</html>

<script>
  Vue.component('checkbox-item', {
    template: `
          <label class="checkbox-item">
            <input type="checkbox" :checked="value"
                   @change="$emit('input', $event.target.checked)"
                   class="checkbox-input">
            <span class="checkbox-label">
              <slot></slot>
            </span>
          </label>
        `,
    data: function() {
      return {
        checkData: null
      }
    },
    props: ['value']
  })
  new Vue({
    el: '#app',
  })
</script>

(ЭТА ВЕРСИЯ РАБОТАЕТ, НО ВНОВЬ НУЖНА, ЧТОБЫ НУЖНЫ ДАННЫЕ, ЧТОБЫ НЕ ИСПОЛЬЗОВАТЬСЯ В КОРНЕВОЙ ИНСТАНЦИИ)

<body>
  <script src="https://unpkg.com/vue@2.6.10"></script>
  <div id="app">
    <checkbox-item v-model="checkData">Active</checkbox-item>
    {{ checkData }}
  </div>
</body>

<script>
  Vue.component('checkbox-item', {
    template: `
          <label class="checkbox-item">
            <input type="checkbox" :checked="value"
                   @change="$emit('input', $event.target.checked)"
                   class="checkbox-input">
            <span class="checkbox-label">
              <slot></slot>
            </span>
          </label>
        `,
    props: ['value']
  })
  new Vue({
    el: '#app',
    data: {
      checkData: null
    }
  })
</script>

Ошибка, которую я получаю:

[Vue warn]: свойство или метод "checkData" не определены в экземпляре, но на него ссылаются во времявизуализации.Убедитесь, что это свойство является реактивным, либо в параметре данных, либо для компонентов на основе классов, инициализируя свойство.См .: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

И checkData не реагирует, как это было в рабочем примере.

РЕДАКТИРОВАТЬ: Хорошо, вот что работает!Я определенно собираюсь изучить использование SFC и других методов организации кода, но пока это все еще в одном HTML-файле.Кто-нибудь видит причину, по которой это не сработает в долгосрочной перспективе?

  <body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <div id="app">
        <checkbox-item></checkbox-item>
    </div>
  </body>
</html>

<script>
  Vue.component('checkbox-item', {
    template: `
      <label class="checkbox-item">
        <input type="checkbox" v-model="checkData"
               class="checkbox-input">
        <span class="checkbox-label">
          <slot>Active: {{checkData}}</slot>
        </span>
      </label>
    `,
    data: function(){
      return {
        checkData: this.checked
      }
    },
  })
  new Vue({
    el: '#app',
  })
</script>

1 Ответ

1 голос
/ 30 мая 2019

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

<html>
<!-- Your existing nonfunctional example -->
<body>
  <script src="https://unpkg.com/vue@2.6.10"></script>
  <div id="app">
    <!-- Both v-model and {{ checkData }}
      are asking about the root vue's checkData,
      but you took that off. This is why you have an error -->
    <checkbox-item v-model="checkData">Active</checkbox-item>
    {{ checkData }}
  </div>
</body>

</html>

Что происходит в нефункциональном примере?

Когда вы говорите v-model="checkData" в нефункциональном примере, это говорит компоненту Parent (Root) Vue найти checkData в его локальной области видимости и v-bind:value="checkData" и v-on:input="checkData = $event.target.value"

Включение вашего флажка-item reusable

Ваш компонент чудесно повторно используется как есть.

Единственное изменение, которое я бы сделал в вашем checkbox-item, - это пропуск v-on="$listeners" и v-bind="$attrs" через input элемент, и удалите явное «значение» в подпорке.

Для любого низкоуровневого, многократно используемого компонента пользовательского интерфейса вы захотите получать и выводить данные.Использование v-модели и хранение данных в родительском компоненте - это именно то, что вы хотите сделать.Хранение данных в корневом компоненте кажется неуклюжим, поэтому часто бывают компоненты среднего уровня.

Чтобы продемонстрировать это, я составил список ботаников, которые могут быть либо счастливыми, либо грустными, и использовать ваш флажок для обновления ихstate.

Использование в компоненте Root Vue
<body>
  <script src="https://unpkg.com/vue@2.6.10"></script>
  <div id="app">
    <!-- If you wanted to take in data,
        you would pass in the nerds array as a Prop
        into nerd-list _from_ the root Vue instance -->
    <nerd-list/> 
  </div>
</body>

<script>
  Vue.component('nerd-list', {
   template: '<div>
     <h1>List of nerds and if they are happy</h1>
     <div v-for="nerd in nerds" :key="nerd.id">
       {{ nerd.name }}
       <checkbox-item v-model="nerd.happy">Happy</checkbox-item>
     </div>
   </div>',
  data() {
    return {
      nerds: [
        { name: 'Jess', happy: true, id: 1 },
        { name: 'Tiffany', happy: true, id: 2 },
      ]
    };
  },
});

  Vue.component('checkbox-item', {
    template: `
          <label class="checkbox-item">
            <input type="checkbox" :checked="value"
                   @change="$emit('input', $event.target.checked)"
                   class="checkbox-input">
            <span class="checkbox-label">
              <slot></slot>
            </span>
          </label>
        `,
    props: ['value']
  })
  new Vue({
    el: '#app',
    data: {}, // any data in here could be used to pass props into the nerd-list.
  })
</script>

Наконец, как вы можете заметить, запись всего этого в файлы Javascript может показаться немного громоздкой.Я настоятельно рекомендую использовать компоненты Vue CLI и Vue SFC для лучшего впечатления.

...