我尝试在created
的vuejs内调用我的jquery自定义滑块,但不幸的是它没有用。仅当我将代码放在mounted
上时,它才起作用,但是当我离开页面并返回同一页面时,它就停止了。
这是我的代码。
export default {
//This only worked on first load and never to work again on leaving the page and coming back!
mounted() {
require("./slider.js");
},
...
}
...
export default {
//This never works!
created() {
require("./slider.js");
},
...
}
slider.js
//Star slider
(function($) {
'use strict';
var pluginName = 'slider',
defaults = {
next: '.slider-nav__next',
prev: '.slider-nav__prev',
item: '.slider__item',
dots: false,
dotClass: 'slider__dot',
autoplay: false,
autoplayTime: 3000,
};
function slider(element, options) {
this.$document = $(document);
this.$window = $(window);
this.$element = $(element);
this.options = $.extend({}, defaults, options);
this.init();
};
slider.prototype.init = function() {
this.setup();
this.attachEventHandlers();
this.update();
};
slider.prototype.setup = function(argument) {
this.$slides = this.$element.find(this.options.item);
this.count = this.$slides.length;
this.index = 0;
this.$next = $(this.options.next);
this.$prev = $(this.options.prev);
this.$canvas = $(document.createElement('div'));
this.$canvas.addClass('slider__canvas').appendTo(this.$element);
this.$slides.appendTo(this.$canvas);
this.$dots = $(this.options.dots);
this.$dots.length && this.createDots();
};
slider.prototype.createDots = function() {
var dots = [];
var dotClassName = this.options.dotClass;
this.$element.children().find('.slider__item__title').each(function(__index, el) {
var __title = $(this).text();
dots[__index] = '<div data-index="' + __index + '" class="' + dotClassName + '">' + __title + '</div>';
});
this.$dots.append(dots);
}
slider.prototype.attachEventHandlers = function() {
this.$element.on('prev.' + pluginName, this.prev.bind(this));
this.$document.on('click', this.options.prev, (function(e) {
this.$element.trigger('prev.' + pluginName);
}).bind(this));
this.$element.on('next.' + pluginName, this.next.bind(this));
this.$document.on('click', this.options.next, (function(e) {
this.$element.trigger('next.' + pluginName);
}).bind(this));
this.$element.on('update.' + pluginName, this.update.bind(this));
this.$window.on('resize load', (function(e) {
this.$element.trigger('update.' + pluginName);
}).bind(this));
this.$element.on('jump.' + pluginName, this.jump.bind(this));
this.$document.on('click', ('.' + this.options.dotClass), (function(e) {
var index = parseInt($(e.target).attr('data-index'));
this.$element.trigger('jump.' + pluginName, index);
}).bind(this));
this.$element.on('autoplay.' + pluginName, this.autoplay.bind(this));
this.$element.on('autoplayOn.' + pluginName, this.autoplayOn.bind(this));
this.$element.on('autoplayOff.' + pluginName, this.autoplayOff.bind(this));
this.$element.bind('prev.' + pluginName + ' next.' + pluginName + ' jump.' + pluginName, this.autoplay.bind(this));
this.options.autoplay && this.$element.trigger('autoplayOn.' + pluginName);
};
slider.prototype.next = function(e) {
this.index = (this.index + 1) % this.count;
this.slide();
};
slider.prototype.prev = function(e) {
this.index = Math.abs(this.index - 1 + this.count) % this.count;
this.slide();
};
slider.prototype.jump = function(e, index) {
this.index = index % this.count;
this.slide();
}
slider.prototype.autoplayOn = function(argument) {
this.options.autoplay = true;
this.$element.trigger('autoplay.' + pluginName);
};
slider.prototype.autoplayOff = function() {
this.autoplayClear();
this.options.autoplay = false;
}
slider.prototype.autoplay = function(argument) {
this.autoplayClear();
if (this.options.autoplay) {
this.autoplayId = setTimeout((function() {
this.$element.trigger('next.' + pluginName);
this.$element.trigger('autoplay.' + pluginName);
}).bind(this), this.options.autoplayTime);
}
};
slider.prototype.autoplayClear = function() {
this.autoplayId && clearTimeout(this.autoplayId);
}
slider.prototype.slide = function(index) {
undefined == index && (index = this.index);
var position = index * this.width * -1;
this.$canvas.css({
'transform': 'translate3d(' + position + 'px, 0, 0)',
});
this.updateCssClass();
};
slider.prototype.update = function() {
this.width = this.$element.width();
this.$canvas.width(this.width * this.count);
this.$slides.width(this.width);
this.slide();
};
slider.prototype.updateCssClass = function() {
this.$slides
.removeClass('x__slider-active')
.eq(this.index)
.addClass('x__slider-active');
this.$dots
.find('.' + this.options.dotClass)
.removeClass('x__slider-active')
.eq(this.index)
.addClass('x__slider-active');
}
$.fn[pluginName] = function(options) {
return this.each(function() {
!$.data(this, pluginName) && $.data(this, pluginName, new slider(this, options));
});
};
})(window.jQuery);
$('#x__slider').slider({
prev: '#x__slider-prev',
next: '#x__slider-next',
dots: '#x__slider-dots',
autoplay: true,
});
//End slider
答案 0 :(得分:1)
您注意到,将代码放入创建的生命周期挂钩后,代码将无法正常工作。为了弄清楚原因,我们需要深入研究the lifecycle hooks。滑块的工作原理是找到一个元素,然后将其转换为滑块。
运行创建的挂钩时,尚无组件渲染。在生命周期挂钩beforeMount
之后,只有组件中的html。之后,您可以使用的第一个生命周期挂钩是mounted
挂钩。
您使用require(..)
运行滑块的代码。需要您的滑块文件运行IIFE。包含它之后,就无需再次运行它。再次加载滑块时,文件已从内存加载,因为之前已经“需要”。
最好将代码完全放在组件生命周期挂钩之外,然后使用从文件中导出的一些初始化函数。
我建议不要在Vue应用程序中使用jQuery。 jQuery和Vue都可以操作DOM。 Vue没有jQuery不能做的事,但是您可能需要重新考虑如何构造元素。如果您不想自己写任何东西,那么那里还有几个预制的滑块。
如果您需要使其与jQuery一起使用,最好的选择是稍微更改一下slide.js文件以在底部导出初始化代码。
export default function (element) {
$(element).slider({
prev: '#x__slider-prev',
next: '#x__slider-next',
dots: '#x__slider-dots',
autoplay: true,
});
}
代替使用require
,只需将其导入组件顶部即可。
<script>
import sliderInit from './slider';
export default {
// ...
更改模板以在元素上包含a ref
。这样一来,您就可以引用DOM元素,而无需冒页面上重复ID的风险。
<template>
<div ref="slider">
<div class="slide">
<!-- You get the idea -->
</div>
</div>
</template>
现在,我们只需要初始化滑块即可。最好的方法是执行我们刚刚在安装的钩子中导入的功能。您可能需要稍等片刻,以使引用保持不变
mounted () {
// Option 1
sliderInit(this.$refs.slider);
// Option 2
this.$nextTick(() => {
sliderInit(this.$refs.slider);
});
}