vue项目引入vue-scrollTo插件的完整步骤:
使用npm安装则如下:
1、安装vue-scrollto
npm install --save vue-scrollto
2、项目根目录src文件夹下创建scroll文件夹(文件夹名字自定义,我习惯创建名为scroll),并在scroll文件夹内部创建scrollTo.js(该js文件名自定义,我习惯创建名为scrollTo.js,方便理解),将下面的js复制并粘贴到scrollTo.js中
import BezierEasing from "bezier-easing";
import easings from "./easings";
import _ from "./utils";
const abortEvents = [
"mousedown",
"wheel",
"DOMMouseScroll",
"mousewheel",
"keyup",
"touchmove"
];
let defaults = {
container: "body",
duration: 500,
easing: "ease",
offset: 0,
force: true,
cancelable: true,
onStart: false,
onDone: false,
onCancel: false,
x: false,
y: true
};
export function setDefaults(options) {
defaults = Object.assign({}, defaults, options);
}
export const scroller = () => {
let element; // element to scroll to
let container; // container to scroll
let duration; // duration of the scrolling
let easing; // easing to be used when scrolling
let offset; // offset to be added (subtracted)
let force; // force scroll, even if element is visible
let cancelable; // indicates if user can cancel the scroll or not.
let onStart; // callback when scrolling is started
let onDone; // callback when scrolling is done
let onCancel; // callback when scrolling is canceled / aborted
let x; // scroll on x axis
let y; // scroll on y axis
let initialX; // initial X of container
let targetX; // target X of container
let initialY; // initial Y of container
let targetY; // target Y of container
let diffX; // difference
let diffY; // difference
let abort; // is scrolling aborted
let abortEv; // event that aborted scrolling
let abortFn = e => {
if (!cancelable) return;
abortEv = e;
abort = true;
};
let easingFn;
let timeStart; // time when scrolling started
let timeElapsed; // time elapsed since scrolling started
let progress; // progress
function scrollTop(container) {
let scrollTop = container.scrollTop;
if (container.tagName.toLowerCase() === "body") {
// in firefox body.scrollTop always returns 0
// thus if we are trying to get scrollTop on a body tag
// we need to get it from the documentElement
scrollTop = scrollTop || document.documentElement.scrollTop;
}
return scrollTop;
}
function scrollLeft(container) {
let scrollLeft = container.scrollLeft;
if (container.tagName.toLowerCase() === "body") {
// in firefox body.scrollLeft always returns 0
// thus if we are trying to get scrollLeft on a body tag
// we need to get it from the documentElement
scrollLeft = scrollLeft || document.documentElement.scrollLeft;
}
return scrollLeft;
}
function step(timestamp) {
if (abort) return done();
if (!timeStart) timeStart = timestamp;
timeElapsed = timestamp - timeStart;
progress = Math.min(timeElapsed / duration, 1);
progress = easingFn(progress);
topLeft(
container,
initialY + diffY * progress,
initialX + diffX * progress
);
timeElapsed < duration ? window.requestAnimationFrame(step) : done();
}
function done() {
if (!abort) topLeft(container, targetY, targetX);
timeStart = false;
_.off(container, abortEvents, abortFn);
if (abort && onCancel) onCancel(abortEv, element);
if (!abort && onDone) onDone(element);
}
function topLeft(element, top, left) {
if (y) element.scrollTop = top;
if (x) element.scrollLeft = left;
if (element.tagName.toLowerCase() === "body") {
// in firefox body.scrollTop doesn't scroll the page
// thus if we are trying to scrollTop on a body tag
// we need to scroll on the documentElement
if (y) document.documentElement.scrollTop = top;
if (x) document.documentElement.scrollLeft = left;
}
}
function scrollTo(target, _duration, options = {}) {
if (typeof _duration === "object") {
options = _duration;
} else if (typeof _duration === "number") {
options.duration = _duration;
}
element = _.$(target);
if (!element) {
return console.warn(
"[vue-scrollto warn]: Trying to scroll to an element that is not on the page: " +
target
);
}
container = _.$(options.container || defaults.container);
duration = options.duration || defaults.duration;
easing = options.easing || defaults.easing;
offset = options.offset || defaults.offset;
offset = offset - 60
force = options.hasOwnProperty("force")
? options.force !== false
: defaults.force;
cancelable = options.hasOwnProperty("cancelable")
? options.cancelable !== false
: defaults.cancelable;
onStart = options.onStart || defaults.onStart;
onDone = options.onDone || defaults.onDone;
onCancel = options.onCancel || defaults.onCancel;
x = options.x === undefined ? defaults.x : options.x;
y = options.y === undefined ? defaults.y : options.y;
var cumulativeOffsetContainer = _.cumulativeOffset(container);
var cumulativeOffsetElement = _.cumulativeOffset(element);
if (typeof offset === "function") {
offset = offset();
}
initialY = scrollTop(container);
targetY = cumulativeOffsetElement.top -
cumulativeOffsetContainer.top +
offset;
initialX = scrollLeft(container);
targetX = cumulativeOffsetElement.left -
cumulativeOffsetContainer.left +
offset;
abort = false;
diffY = targetY - initialY;
diffX = targetX - initialX;
if (!force) {
const containerTop = initialY;
const containerBottom = containerTop + container.offsetHeight;
const elementTop = targetY;
const elementBottom = elementTop + element.offsetHeight;
if (elementTop >= containerTop && elementBottom <= containerBottom) {
return;
}
}
if (typeof easing === "string") {
easing = easings[easing] || easings["ease"];
}
easingFn = BezierEasing.apply(BezierEasing, easing);
if (!diffY && !diffX) return;
if (onStart) onStart(element);
_.on(container, abortEvents, abortFn, { passive: true });
window.requestAnimationFrame(step);
return () => {
abortEv = null;
abort = true;
};
}
return scrollTo;
};
const _scroller = scroller();
export default _scroller;
并在当前文件夹内部创建easings.js,(这个文件在scrollTo.js中引入,可查看上面的代码示例)
export default {
ease: [0.25, 0.1, 0.25, 1.0],
linear: [0.00, 0.0, 1.00, 1.0],
"ease-in": [0.42, 0.0, 1.00, 1.0],
"ease-out": [0.00, 0.0, 0.58, 1.0],
"ease-in-out": [0.42, 0.0, 0.58, 1.0]
};
以及创建utils.js,(这个文件在scrollTo.js中引入,可查看上面的代码示例)
// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection
let supportsPassive = false;
try {
let opts = Object.defineProperty({}, "passive", {
get: function() {
supportsPassive = true;
}
});
window.addEventListener("test", null, opts);
} catch (e) {}
export default {
$(selector) {
if (typeof selector !== "string") {
return selector;
}
return document.querySelector(selector);
},
on(element, events, handler, opts = { passive: false }) {
if (!(events instanceof Array)) {
events = [events];
}
for (let i = 0; i < events.length; i++) {
element.addEventListener(
events[i],
handler,
supportsPassive ? opts : false
);
}
},
off(element, events, handler) {
if (!(events instanceof Array)) {
events = [events];
}
for (let i = 0; i < events.length; i++) {
element.removeEventListener(events[i], handler);
}
},
cumulativeOffset(element) {
let top = 0;
let left = 0;
do {
top += element.offsetTop || 0;
left += element.offsetLeft || 0;
element = element.offsetParent;
} while (element);
return {
top: top,
left: left
};
}
};
3、将scrollTo.js引入到main.js中
//因为scrollTo是一个方法所以要用{}包裹
import {scroller} from '@/scroll/scrollTo.js'
4、将scrollTo这个方法挂载到vue原型上,全局可用
//把scrollTo挂载到vue原型上,想用就用(为什么叫$scrollTo,这个是自定义的,喜欢叫什么就定义什么,本人出于自己的习惯喜欢加个$+方法名)
Vue.prototype.$scrollTo = scroller()
5、在页面的使用方法
//下面简单说一下用法,直接使用this.$scrollTo('id+dom元素的id名字');就可以实现类似于锚点的点击效果,点击导航并滚动到某个位置
//这是一个点击事件的回调
handleClick() {
this.$scrollTo('#condition');
}