Vue v-on: घटक पर क्लिक से काम नहीं होता है


186

मैं एक घटक के अंदर क्लिक निर्देश का उपयोग करने की कोशिश कर रहा हूं, लेकिन यह काम नहीं करता है। जब मैं क्लिक करता हूं तो घटक नोटिंग्स तब होता है जब मुझे कंसोल में एक 'टेस्ट क्लिक' मिलना चाहिए। मुझे कंसोल में कोई त्रुटि नहीं दिखाई देती है, इसलिए मुझे नहीं पता कि मैं क्या गलत कर रहा हूं।

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>vuetest</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

App.vue

<template>
  <div id="app">
    <test v-on:click="testFunction"></test>
  </div>
</template>

<script>
import Test from './components/Test'

export default {
  name: 'app',
  methods: {
    testFunction: function (event) {
      console.log('test clicked')
    }
  },
  components: {
    Test
  }
}
</script>

Test.vue (घटक)

<template>
  <div>
    click here
  </div>
</template>

<script>
export default {
  name: 'test',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

जवाबों:


333

यदि आप किसी घटक के मूल तत्व पर एक मूल घटना सुनना चाहते हैं, तो आपको इसके लिए .native संशोधक का उपयोग करना होगाv-on , जैसे:

<template>
  <div id="app">
    <test v-on:click.native="testFunction"></test>
  </div>
</template>

या आशुलिपि में, जैसा कि टिप्पणी में सुझाया गया है, आप भी कर सकते हैं:

<template>
  <div id="app">
    <test @click.native="testFunction"></test>
  </div>
</template>

3
या आशुलिपि@click.native="testFunction"
पियर

75
एक मूल घटना क्या है या यह अन्य सामान्य घटनाओं से कैसे भिन्न है ? जड़ तत्वों के लिए यह विशेष मामला क्यों ???
मि। क्लान


9
देशी संशोधक को सलाह दी जाती है कि इसका उपयोग व्रत में किया जाए। यदि आवश्यक हो तो ही इसका उपयोग करें। इसे प्राप्त करने के सही तरीके के लिए @ jim-mcneely देखें अर्थात बच्चे तत्व से घटनाओं को छोड़ना और फिर इसे माता-पिता में पुनर्जीवित करना।
देक्निमयी


32

मुझे लगता है $emitकि आप जो पूछ रहे हैं उसके लिए फ़ंक्शन बेहतर काम करता है। यह आपके घटक को Vue उदाहरण से अलग रखता है ताकि यह कई संदर्भों में पुन: प्रयोज्य हो।

// Child component
<template>
  <div id="app">
    <test @click="$emit('test-click')"></test>
  </div>
</template>

इसे HTML में इस्तेमाल करें

// Parent component
<test @test-click="testFunction">

5
मेरा मानना ​​है कि यह सही उत्तर है। घटनाओं के जोड़ने के घटक के भीतर संभाल। कॉल करने के लिए क्लिक इवेंट के "संस्करण" के मूल घटक की चिंता न करें। मैं वास्तव में घटक के नीचे दिए गए उत्तर के रूप में इसे लागू करता हूं @click="$emit('click')"और इस तरह से मूल घटक नियमित रूप से उपयोग करता है@click
नेल्सन रोड्रिगेज

2
मैं थोड़ा उलझन में हूँ। क्या $ emit हिस्सा शायद परीक्षण घटक टेम्पलेट में होना चाहिए?
स्टीफन फैबियन

1
@ नेल्सन रोड्रिगेज ने क्या कहा। का उपयोग करें @click="$emit('click')"
निफेल

20

यह @Neps का जवाब है, लेकिन विवरण के साथ।


नोट : @ सौरभ का उत्तर अधिक उपयुक्त है यदि आप अपने घटक को संशोधित नहीं करना चाहते हैं या उस तक पहुंच नहीं है।


@ सिर्फ काम क्यों नहीं कर सकता?

घटक जटिल हैं। एक घटक एक छोटा फैंसी बटन आवरण हो सकता है, और दूसरा एक पूरी तालिका हो सकती है जिसमें तर्क का एक गुच्छा होता है। Vue नहीं जानता कि आप वास्तव में क्या उम्मीद करते हैं जब आप बांधते हैं v-modelया उपयोग करते हैं, v-onतो उस सभी को घटक के निर्माता द्वारा संसाधित किया जाना चाहिए।

क्लिक इवेंट को कैसे हैंडल करें

Vue डॉक्स के अनुसार , $emitमाता-पिता के लिए घटनाओं को पारित करता है। डॉक्स से उदाहरण:

मुख्य फ़ाइल

<blog-post
  @enlarge-text="onEnlargeText"
/>

अंग

<button @click="$emit('enlarge-text')">
  Enlarge text
</button>

( @है v-on आशुलिपि )

घटक मूल clickघटना को संभालता है और माता-पिता का उत्सर्जन करता है@enlarge-text="..."

enlarge-textइसे ऐसे बदला जा सकता है clickजैसे यह देखने के लिए कि हम एक देशी क्लिक घटना को संभाल रहे हैं:

<blog-post
  @click="onEnlargeText"
></blog-post>
<button @click="$emit('click')">
  Enlarge text
</button>

लेकिन वह सब नहीं है। $emitएक घटना के साथ एक विशिष्ट मूल्य पारित करने की अनुमति देता है। मूल के मामले में click, मूल्य माउसईवेंट (जेएस घटना है जिसका वीयू से कोई लेना-देना नहीं है)।

Vue उस घटना को एक $eventचर में संग्रहीत करता है । इसलिए, $eventमूल ईवेंट उपयोग की छाप बनाने के लिए किसी ईवेंट के साथ उत्सर्जन करना सबसे अच्छा होगा :

<button v-on:click="$emit('click', $event)">
  Enlarge text
</button>

8

थोड़ी सी क्रिया लेकिन मैं इसे कैसे करता हूं:

@click="$emit('click', $event)"


8
यह कहाँ जाता है आप इसे वहां क्यों लगाते हैं? कृपया इस उत्तर को देखने वाले लोगों के लिए थोड़ा और विवरण जोड़ें?
मिक्स

इस उदाहरण में यह Test.vue घटक में div टैग पर रखा जाएगा। इसके बाद आप v- ऑन का उपयोग कर सकते हैं: App.vue में घटक परीक्षण का उपयोग करते समय = "testFunction" या @ क्लिक = "testFunction" पर क्लिक करें
टिम

मैंने इसे बदल दिया $emitलेकिन कुछ नहीं हो रहा है। क्या मुझे इसके अतिरिक्त कुछ करने की आवश्यकता है $emit? jsfiddle.net/xwvhy6a3
रिचर्ड बैराक्लो

@RichardBarraclough आपका घटक अब आपके कस्टम ईवेंट "clickTreeItem" का उत्सर्जन करता है। वी-ऑन:: अगली क्या उस घटक के उपयोग में है कि घटना से कोई लेना देना संभालने के लिए है myEvent = "MyMethod"
Neps

5

घटकों की मूल घटनाएं सीधे मूल तत्वों से सुलभ नहीं हैं। इसके बजाय आपको प्रयास करना चाहिए v-on:click.native="testFunction", या आप Testघटक से भी एक घटना का उत्सर्जन कर सकते हैं । की तरह v-on:click="$emit('click')"


4

जैसा कि VueCONF US 2019 में क्रिस फ्रिट्ज़ (Vue.js Core Team Emeriti ) ने उल्लेख किया है

अगर हमने किआ दर्ज किया था .nativeऔर फिर बेस इनपुट के मूल तत्व को इनपुट से बदलकर अचानक इस घटक को तोड़ दिया गया है और यह स्पष्ट नहीं है और वास्तव में, आप इसे तुरंत पकड़ भी नहीं सकते हैं जब तक कि आपके पास वास्तव में अच्छा परीक्षण न हो। इसके बजाय आप वर्तमान में विचार कर रहे.native संशोधक के उपयोग से बचें, जो Vue 3 में हटाए जाएंगे, आप स्पष्ट रूप से यह परिभाषित कर पाएंगे कि माता-पिता को इस बात की परवाह हो सकती है कि कौन से तत्व श्रोताओं के लिए जोड़े गए हैं ...

Vue 2 के साथ

का उपयोग कर $listeners:

इसलिए, यदि आप Vue 2 का उपयोग कर रहे हैं, तो इस समस्या को हल करने के लिए एक बेहतर विकल्प एक पूरी तरह से पारदर्शी आवरण तर्क का उपयोग करना होगा । इसके लिए Vue एक $listenersसंपत्ति प्रदान करता है जिसमें घटक पर उपयोग किए जा रहे श्रोताओं का एक ऑब्जेक्ट होता है। उदाहरण के लिए:

{
  focus: function (event) { /* ... */ }
  input: function (value) { /* ... */ },
}

और फिर हमें बस घटक की तरह जोड़ना v-on="$listeners"होगा test:

Test.vue (बाल घटक)

<template>
  <div v-on="$listeners">
    click here
  </div>
</template>

अब <test>घटक पूरी तरह से पारदर्शी आवरण है , जिसका अर्थ है कि यह बिल्कुल एक सामान्य <div>तत्व की तरह उपयोग किया जा सकता है : सभी श्रोता बिना .nativeसंशोधक के काम करेंगे ।

डेमो:

Vue.component('test', {
  template: `
    <div class="child" v-on="$listeners">
      Click here
    </div>`
})

new Vue({
  el: "#myApp",
  data: {},
  methods: {
    testFunction: function(event) {
      console.log('test clicked')
    }
  }
})
div.child{border:5px dotted orange; padding:20px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
  <test @click="testFunction"></test>
</div>

$emitविधि का उपयोग:

हम $emitइस उद्देश्य के लिए विधि का उपयोग भी कर सकते हैं , जो हमें मूल घटक में बाल घटकों की घटनाओं को सुनने में मदद करता है। इसके लिए, हमें सबसे पहले बाल घटक से एक कस्टम घटना का उत्सर्जन करना होगा :

Test.vue (बाल घटक)

<test @click="$emit('my-event')"></test>

महत्वपूर्ण: हमेशा ईवेंट नामों के लिए कबाब-केस का उपयोग करें। अधिक जानकारी के लिए और इस बिंदु को पुनः दर्ज करने के लिए कृपया इस उत्तर को देखें: VueJS घटक से अभिभावक के लिए गणना किए गए मान से गुजरता है

अब, हमें मूल घटक में इस उत्सर्जित कस्टम घटना को सुनना होगा:

App.vue

<test @my-event="testFunction"></test>

इसलिए, मूल रूप से v-on:clickया शॉर्टहैंड के बजाय @clickहम केवल v-on:my-eventया केवल उपयोग करेंगे @my-event

डेमो:

Vue.component('test', {
  template: `
    <div class="child" @click="$emit('my-event')">
      Click here
    </div>`
})

new Vue({
  el: "#myApp",
  data: {},
  methods: {
    testFunction: function(event) {
      console.log('test clicked')
    }
  }
})
div.child{border:5px dotted orange; padding:20px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
  <test @my-event="testFunction"></test>
</div>


Vue 3 के साथ

का उपयोग कर v-bind="$attrs":

Vue 3 कई मायनों में हमारे जीवन को बहुत आसान बनाने जा रहा है। इसके लिए उदाहरणों में से एक यह है कि यह हमें केवल उपयोग करके बहुत कम विन्यास के साथ एक सरल पारदर्शी आवरण बनाने में मदद करेगा v-bind="$attrs"। बाल घटकों पर इसका उपयोग करने से न केवल हमारे श्रोता सीधे माता-पिता से काम करेंगे, बल्कि किसी अन्य विशेषता भी <div>केवल एक सामान्य की तरह काम करेंगे ।

इसलिए, इस प्रश्न के संबंध में, हमें Vue 3 में कुछ भी अपडेट करने की आवश्यकता नहीं होगी और आपका कोड अभी भी ठीक काम करेगा <div>जैसा कि यहां मूल तत्व है और यह स्वचालित रूप से सभी बच्चे की घटनाओं को सुनेगा।

डेमो # 1:

const { createApp } = Vue;

const Test = {
  template: `
    <div class="child">
      Click here
    </div>`
};

const App = {
  components: { Test },
  setup() {
    const testFunction = event => {
      console.log("test clicked");
    };
    return { testFunction };
  }
};

createApp(App).mount("#myApp");
div.child{border:5px dotted orange; padding:20px;}
<script src="//unpkg.com/vue@next"></script>
<div id="myApp">
  <test v-on:click="testFunction"></test>
</div>

लेकिन नेस्टेड तत्वों के साथ जटिल घटकों के लिए, जहां हमें <input />मूल लेबल के बजाय विशेषताओं और घटनाओं को मुख्य रूप से लागू करने की आवश्यकता होती हैv-bind="$attrs"

डेमो # 2:

const { createApp } = Vue;

const BaseInput = {
  props: ['label', 'value'],
  template: `
    <label>
      {{ label }}
      <input v-bind="$attrs">
    </label>`
};

const App = {
  components: { BaseInput },
  setup() {
    const search = event => {
      console.clear();
      console.log("Searching...", event.target.value);
    };
    return { search };
  }
};

createApp(App).mount("#myApp");
input{padding:8px;}
<script src="//unpkg.com/vue@next"></script>
<div id="myApp">
  <base-input 
    label="Search: "
    placeholder="Search"
    @keyup="search">
  </base-input><br/>
</div>


1
यह स्वीकृत उत्तर होना चाहिए। धन्यवाद!
एलिजुनियर

0

से प्रलेखन :

जावास्क्रिप्ट में सीमाओं के कारण, व्यू एक सरणी में निम्नलिखित परिवर्तनों का पता नहीं लगा सकता है:

  1. जब आप सीधे इंडेक्स के साथ एक आइटम सेट करते हैं, जैसे vm.items [indexOfItem] = newValue
  2. जब आप सरणी की लंबाई को संशोधित करते हैं, उदाहरण के लिए vm.items.length = newLength

मेरे मामले में मैं इस समस्या पर ठोकर खाई जब एंगुलर से VUE की ओर प्रस्थान किया। फिक्स काफी आसान था, लेकिन वास्तव में इसे खोजना मुश्किल था:

setValue(index) {
    Vue.set(this.arr, index, !this.arr[index]);
    this.$forceUpdate(); // Needed to force view rerendering
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.