programing

v-on 클릭, 조건이 충족된 경우에만 핸들러 추가

bestcode 2022. 9. 8. 22:18
반응형

v-on 클릭, 조건이 충족된 경우에만 핸들러 추가

에반 씨의 조사 결과, 다음과 같은 제안이 발견되었습니다.https://github.com/vuejs/vue/issues/7349#issuecomment-354937350

그래서 망설임 없이 시도해 보았다.

컴포넌트 템플릿

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

JS 로직

<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

어떤 잘못을 했는지 누가 좀 제안해 주시겠어요?: 생각:

갱신하다
그 길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차 논리로 오염시키는 대신 클릭 핸들러 내부에서 실제로 검사를 수행해야 합니다.템플릿의 가독성을 높일 뿐만 아니라 모든 로직이 추상화되어 이벤트 핸들러의 콜백에 위임되므로 코드를 쉽게 유지할 수 있습니다.

신속한 해결

따라서 빠른 해결책은 실제로 다음 사항을 확인하는 것입니다.toggleSectionElements()올바른 경우에만 기능합니다.dataType존재합니다.이는 guard 절을 사용하여 수행할 수 있습니다.

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
  }
}

권장사항: 원자성분 사용

클릭 이벤트핸들러를 아무것도 하지 않는 요소에 바인드 하는 것은 비용이 많이 들기 때문에 컴포넌트를 분해하여 보다 원자적으로 만들 수도 있습니다.수집 요소는 "섹션" 또는 "요소"의 배열을 수신하는 역할을 하며, 각 "섹션"/"요소"는 다음과 같은 자체 구성요소를 가집니다.

  • 수집 컴포넌트가 있습니다.<my-collection>모든 "섹션" 및 "섹션" 컴포넌트를 수용합니다.
  • "섹션" 컴포넌트는<my-section>요소
  • "component" 컴포넌트는<my-element>요소

이때 VueJ가 매우 강력해집니다.내부에서는 다이내믹 컴포넌트를 사용할 수 있습니다.<my-collection>사용할 컴포넌트를 결정합니다.dataType맞닥뜨린.

이 조작은, 를 실행하는 것으로 행해집니다.v-for수집을 통해, 그리고 나서v-bind:is="..."특정 수집 항목이 "섹션" 또는 "섹션"을 사용해야 하는지 여부를 결정합니다.이 질문은 당초 질문의 범위를 벗어나는 것으로 생각됩니다만, 다음 사항을 고려해 보는 것이 좋습니다.

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>

아래와 같이 변경하기만 하면 동작합니다.

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

또는 핸들러가 마우스 오버라고 불리는 경우

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

여기:

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

그렇지 않은 경우 null을 통과하지만 클릭 시 값은 함수를 예상합니다.비우기 함수를 시도할 수 있습니다.

click: dataType === `section` ? toggleSectionElements : ()=>{}

에서는 Vue 3을 통과할 수 .null듣는 사람에게.이것을 옵션의 체인과 조합하면, 다음과 같이 할 수 있습니다.

@click="handler?.() || null"

이전 브라우저에서도 동일:

@click="handler ? handler() : null"

언급URL : https://stackoverflow.com/questions/54839618/v-on-click-add-handler-only-if-condition-has-been-met

반응형