vue项目引入vue-scrollTo

本文详细介绍了在Vue项目中如何引入和使用vue-scrollTo插件,包括通过npm安装,创建并配置scrollTo.js、easings.js和utils.js文件,然后在main.js中挂载到Vue原型上,最后展示了在页面中如何调用和应用这个滚动到指定位置的方法。

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');
}

<think>我们正在讨论Vue 3与vue-scrollto插件的兼容性问题。 根据我所知,vue-scrollto是一个用于Vue.js的滚动插件,它允许你在页面中平滑滚动到指定元素。 但是,Vue 3引入了许多重大变化,因此许多为Vue 2设计的插件可能不兼容。 经过查找,我了解到vue-scrollto插件有一个支持Vue 3的版本。实际上,插件作者已经更新了插件以支持Vue 3。 我们可以通过安装特定版本的vue-scrollto来使用。通常,安装命令如下: ```bash npm install vue-scrollto@next ``` 或者 ```bash yarn add vue-scrollto@next ``` 这个`@next`标签会安装支持Vue 3的版本(目前是3.x版本)。 使用方式与Vue 2类似,但需要根据Vue 3的插件安装方式进行。 在Vue 3中,我们这样使用: 1. 在main.js中全局引入: ```javascript import { createApp } from 'vue' import VueScrollTo from 'vue-scrollto' const app = createApp(App) app.use(VueScrollTo, { // 可选的全局配置 duration: 500, easing: 'ease', }) app.mount('#app') ``` 2. 在组件中使用: 我们可以通过指令`v-scroll-to`来使用,例如: ```html <button v-scroll-to="'#element'">Scroll to element</button> ``` 或者使用方法调用: ```javascript this.$scrollTo('#element') ``` 但是在Vue 3中,由于没有`this`指向组件实例,我们可以使用注入的方式。不过,插件也提供了另一种方式:我们可以从包中导入`scrollTo`函数。 ```javascript import { scrollTo } from 'vue-scrollto' // 然后在方法中 scrollTo('#element', 500, { easing: 'ease' }) ``` 注意:在Vue 3的setup语法中,我们可以这样使用: ```javascript import { scrollTo } from 'vue-scrollto' export default { setup() { const scrollToElement = () => { scrollTo('#element', 500, { easing: 'ease' }) } return { scrollToElement } } } ``` 另外,我们也可以使用指令方式,在模板中绑定。 如果遇到问题,可以查看官方文档:https://github.com/rigor789/vue-scrollto 总结:Vue 3支持vue-scrollto插件,但需要使用3.x版本(通过安装`vue-scrollto@next`)。 §§相关问题§§ 1. Vue 3中还有哪些常用的滚动插件? 2. 如何在Vue 3中实现平滑滚动效果? 3. vue-scrolltoVue 3中的配置项有哪些?</think>### Vue 3 与 vue-scrollto 插件的兼容性 Vue 3 完全支持 `vue-scrollto` 插件,但需要使用其专门为 Vue 3 设计的版本 **`vue-scrollto@next`**(3.x 版本)。以下是详细说明: #### 1. **安装兼容版本** ```bash npm install vue-scrollto@next # 或 yarn add vue-scrollto@next ``` #### 2. **基础使用方式** **全局注册(main.js)**: ```javascript import { createApp } from 'vue' import VueScrollTo from 'vue-scrollto' const app = createApp(App) app.use(VueScrollTo, { duration: 800, // 滚动时长(ms) offset: -50, // 距离目标的偏移量 easing: 'ease-in' // 缓动效果 }) ``` **组件内使用**: ```vue <template> <!-- 指令方式 --> <button v-scroll-to="'#section-id'">滚动到元素</button> <!-- 方法调用 --> <button @click="scrollToElement">滚动</button> </template> <script setup> import { scrollTo } from 'vue-scrollto' const scrollToElement = () => { scrollTo('#section-id', { duration: 1000, offset: -20 }) } </script> ``` #### 3. **关键配置项** | 参数 | 说明 | 默认值 | |-------------|-------------------------------|----------| | `duration` | 滚动动画时长(毫秒) | `500` | | `offset` | 距离目标元素的偏移量 | `0` | | `easing` | 缓动函数(如 `ease-in-out`) | `'ease'` | | `container` | 滚动容器(默认为 `window`) | `null` | #### 4. **注意事项** - **Vue 2 版本不兼容**:Vue 2 需使用 `vue-scrollto@2.x`,而 Vue 3 必须使用 `@next`(3.x)版本[^1]。 - **TypeScript 支持**:3.x 版本已内置 TypeScript 类型声明。 - **动态目标**:可通过变量绑定目标元素: ```vue <button v-scroll-to="dynamicTarget">滚动</button> ``` --- ### 常见问题解决 1. **滚动无效** 检查目标元素 ID 是否唯一,并确保容器内存在滚动条。 2. **平滑滚动失效** 添加 CSS 保证滚动容器可滚动: ```css html, body { overflow: auto; height: 100%; } ``` 3. **Nuxt 3 集成** 在 `nuxt.config.ts` 中添加: ```javascript export default defineNuxtConfig({ modules: ['@vueuse/nuxt', 'vue-scrollto/nuxt'] }) ``` > 官方文档参考:[vue-scrollto GitHub](https://github.com/rigor789/vue-scrollto)
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值