2

So i have made an accordion/tabs using jQuery, i use jquery .click method on li elements to turn pages/tabs. Now i wanted to integrate Vue.js to display the JSON data i got from jquery on the accordion pages. But when i add .vue class on the accordion and el: '.vue', the jquery .click events do not trigger at all, now the tabs wont turn pages.

Maybe i shouldn't use Vue with Jquery, but i find jQuery is easier to do a simple task like switching between tabs.

PS: im new to Vue

Mostafa
  • 131
  • 1
  • 6

5 Answers5

11

I had the same problem when working on a large project, which had a bunch of existing jQuery code, where we wanted to switch over to Vue.JS, without having to refactor all of the code in one go.

If you are utilizing a module builder like webpack and you have no guarantee for the order of your imports you can do the following:

Once your root application has mounted, broadcast a custom event on the document:

const app = new Vue({
    el: '#app',
    mounted() {
        $(document).trigger('vue-loaded');
    }
});

And then wrap all of your jQuery code in an event listener for your custom event:

$(document).on('vue-loaded', function () {
    const $toggle = $('.js-accordion-toggle');

    $toggle.on('click', function () {
        $(this).toggleClass('test');
    });
});

This worked for me in a large application

Depending on your situation you might need to add $nextTick to ensure that everything has been rendered (https://v2.vuejs.org/v2/api/#mounted)

mounted () {
    this.$nextTick(function () {
        // Code that will run only after the
        // entire view has been rendered
   })
}
tony19
  • 125,647
  • 18
  • 229
  • 307
Emil Rosenius
  • 961
  • 1
  • 9
  • 24
2

This is because your click event is loaded before VUE Component. You are initializing click event on non existing hmtl.

$(document).on('click', '.classname', function(){
 //do action
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Kerim Ayturk
  • 106
  • 6
2

The event handlers are lost because Vue replaces the elements that they're bound to. You can use $.holdReady to delay the $(document).ready until the component is mounted.

$.holdReady(true)

document.addEventListener("DOMContentLoaded", () => {
  new Vue({
    el: "#app-body",
    mounted() {
      $.holdReady(false)
    }
  })
});
hdabrows
  • 36
  • 1
  • 3
1

When Vue is mounted on an element, it removes all event listeners on that DOM. If you want to add custom event listeners, you need to do it after Vue has been mounted in the mounted method:

new Vue({
  el: '#example',
  mounted() {
    const button = document.querySelector('#example > button');
    button.addEventListener('click', () => {
      // ...
    });
    // You can also use JQuery if you want
  },
});
Flimm
  • 136,138
  • 45
  • 251
  • 267
0

Maybe i shouldn't use Vue with Jquery, but i find jQuery is easier to do a simple task like switching between tabs.

It won't be easier to try to integrate jQuery and Vue in the long run. Try to focus on the data driven aspect of Vue.js and the rest will naturally fall into place.

So, for a tabs example in Vue you are simply showing and hiding content based on an underlying data variable, which is set when the user clicks the tab:

<template id="tabs">
  <div>
    <a href="#" @click="tab='foo'">Show Foo</a>
    <a href="#" @click="tab='bar'">Show Bar</a>

    <div v-show="tab === 'foo'">This is Foo</div>
    <div v-show="tab === 'bar'">This is Bar</div>
  </div>
</template>

<script type="text/javascript">
  export default {
    data(){
      return{
        tab: 'foo'
      }
    }
  }

Here's the JSFiddle: https://jsfiddle.net/nst7day3/

When you begin to think in these terms, you'll find that jQuery isn't necessary (or easier) in 99% of cases.

craig_h
  • 31,871
  • 6
  • 59
  • 68
  • Can you make the same fiddle without the template part? i haven't understood that fully yet, and what calls data() ? thanks tho – Mostafa May 25 '17 at 22:19
  • If there were no jQuery plugins, no bootstrap plugins and no large legacy code base (in an ideal world) then such "do everything data-driven from scratch" would be feasible. But in a real world it's a huge pain. There is much more than trivial tabs to re-implement. – Dmitriy Sintsov Apr 04 '18 at 15:44
  • @DmitriySintsov I wasn't suggesting that you should rewrite your entire legacy codebase, but for new projects (which is what I interpreted this question was about), the `Vue` ecosystem is large enough that you can pretty much get a Vue version of any jQuery plugin. `Bootstrap` may be an issue, but there are amazing UI frameworks like [vuetify](https://vuetifyjs.com/), so it's just a matter of looking for appropriate alternatives. – craig_h Apr 04 '18 at 15:53
  • This solution is the only one here addressing the OP's issue with the use of Vue features to solve it. Said that, the root of the issue is not jQuery, add an event to an element with `addEventListener` and it will fail too with Vue 2.0+. This is a huge issue when adding aesthetic events unfeasible with CSS, that are not related to component's logic and not necessarily restricted to component's scope. – Andre Figueiredo May 03 '19 at 11:38