v-on click, добавить обработчик, только если условие выполнено - PullRequest
0 голосов
/ 23 февраля 2019

После некоторого исследования было найдено следующее предложение мистера Эвана: https://github.com/vuejs/vue/issues/7349#issuecomment-354937350

Поэтому, не задумываясь, я попробовал:

Шаблон компонента

<template>
  <div v-on='{ click: dataType === `section` ? toggleSectionElements : null }'>
    ... magic 
  </div>
<template>

JS Logic

<script>
export default {
  name: `product-section`,
  props: [`section`, `sectionName`, `depth`],
  methods: {
    toggleSectionElements() {
      ... magic 
    }
  },
  computed: {
    dataType() {
      if (this.$props.section.sections || this.$props.depth === 0) {
        return `section`
      } else {
        return `element`
      }
    }
  }
}
</script>

Но для описанного случая это приводит к ошибке при рендеринге:

[Vue warn]: Invalid handler for event "click": got null

Может кто-нибудь подсказать, что было сделано неправильно?: think:

Обновление
Путь Data Model выглядит так:

DataModel: {
  mainSectionA: {
    sections: {
      sectionA: {
        sections: {
          elementA: { values: { ... } },     
          elementB: { values: { ... } }
        }
        values: { ... }
      }
      sectionB: {
        elementA: { values: { ... } },
        elementB: { values: { ... } }
      }
    },
    values: { ... }
  },
  mainSectionB: {
    sections: {
      elementA: { values: { ... } },
      elementB: { values: { ... } },  
      elementC: { values: { ... } },
      ... elements
    },
    values: { ... }
  }
}

Ответы [ 3 ]

0 голосов
/ 23 февраля 2019

Просто измените его на приведенное ниже, и оно будет работать

v-on="condition ? { mouseover: handler } : {}"

или, если ваш обработчик называется mouseover

v-on="condition ? { mouseover } : {}"
0 голосов
/ 23 февраля 2019

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

Быстрое решение

Поэтому быстрое решениечтобы фактически убедиться, что toggleSectionElements() будет работать только при наличии правильного dataType.Это может быть достигнуто с помощью защитного предложения:

toggleSectionElements() {
  // Guard clause to prevent further code execution
  if (this.dataType() !== 'section')
    return;

  // Magic here
}

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

methods: {
  // This is just a factory function
  toggleElements() {
    switch (this.dataType()) {
      case 'section':
        return this.toggleSectionElements;
      case 'element':
        // Something else...
    }
  },
  toggleSectionElements() {
    // Magic for section element
  }
}

Предложение: использование атомарных компонентов

Поскольку привязка обработчиков событий щелчка может быть дорогостоящей для элементов, которые в конечном итоге ничего не делают, вы также можете разбить компонент на более атомарный.Элемент коллекции будет отвечать за получение массива «section» или «element», и каждый «section» / «element» будет иметь свой собственный компонент, примерно такой:

  • У вас естькомпонент коллекции, скажем, <my-collection>, который содержит все компоненты "section" и "element"
  • компонент "section" будет использовать <my-section> component
  • компонент "element" будет использовать <my-element> component

Это когда VueJS становится действительно мощным: вы можете использовать динамический компонент внутри <my-collection>, чтобы определить, какой компонент использовать в зависимости от dataType.

Это делается путем запуска v-for через коллекцию, а затем с помощью v-bind:is="...", чтобы определить, должен ли определенный элемент коллекции использовать «section» или «element».Я понимаю, что это, вероятно, выйдет за рамки вашего первоначального вопроса, но стоит рассмотреть этот вариант:

const collectionComponent = Vue.component('my-collection', {
  template: '#my-collection-component',
  data: function() {
    return {
      collection: [{
        dataType: 'section',
        description: 'Hello I am section 1'
      }, {
        dataType: 'element',
        description: 'Hello I am element 1'
      }, {
        dataType: 'section',
        description: 'Hello I am section 2'
      }, {
        dataType: 'element',
        description: 'Hello I am element 2'
      }]
    }
  },
  methods: {
    componentToUse(dataType) {
      return 'my-' + dataType;
    }
  }
});

const sectionComponent = Vue.component('my-section', {
  template: '#my-section-component',
  props: ['itemData'],
  methods: {
    toggle() {
      console.log('Doing some magic.');
    }
  }
});

const elementComponent = Vue.component('my-element', {
  template: '#my-element-component',
  props: ['itemData']
});

new Vue({
  el: '#app'
});
.box {
  border: 1px solid #999;
  cursor: pointer;
  margin: 10px;
  padding: 10px;
}

.box:hover {
  background-color: #eee;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <my-collection />
</div>

<script type="text/x-template" id="my-collection-component">
  <div>
    <component
      v-for="(item, i) in collection"
      v-bind:key="i"
      v-bind:is="componentToUse(item.dataType)"
      v-bind:itemData="item" />
  </div>
</script>

<script type="text/x-template" id="my-section-component">
  <div @click="toggle" class="box">
    <h1>{{ itemData.dataType }}</h1>
    <p>{{ itemData.description }}</p>
    <p>Clicking on me will invoke a section-specific logic</p>
  </div>
</script>

<script type="text/x-template" id="my-element-component">
  <div class="box">
    <h1>{{ itemData.dataType }}</h1>
    <p>{{ itemData.description }}</p>
    <p>Clicking on me will do nothing</p>
  </div>
</script>
0 голосов
/ 23 февраля 2019

здесь:

click: dataType === `section` ? toggleSectionElements : null

в неравном случае вы передаете значение NULL, но значение при нажатии ожидает функцию.Вы можете попробовать функцию emptry:

click: dataType === `section` ? toggleSectionElements : ()=>{}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...