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
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
Share Improve this question asked May 23, 2017 at 11:55 MostafaMostafa 1291 silver badge6 bronze badges 4- 1 Of course it will overwrite handlers bound with jQuery. You should either use delegation or use directive instead. – dfsq Commented May 23, 2017 at 11:57
- Can you create the Vue instance inside the accordion? Maybe one per page. – Kos Commented May 23, 2017 at 12:15
- You should init accordion in vue hooks like mounted – Kirill Matrosov Commented May 23, 2017 at 12:28
- 1 Make VueJS and jQuery play nice – Roy J Commented May 23, 2017 at 12:37
5 Answers
Reset to default 11I 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/v2/api/#mounted)
mounted () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}
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 ponent is mounted.
$.holdReady(true)
document.addEventListener("DOMContentLoaded", () => {
new Vue({
el: "#app-body",
mounted() {
$.holdReady(false)
}
})
});
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./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
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
},
});
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/nst7day3/
When you begin to think in these terms, you'll find that jQuery isn't necessary (or easier) in 99% of cases.