我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Vue的指令中实现传递更多参数

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Vue的指令中实现传递更多参数

概要

我们在使用Vue的开发项目中,经常用自定义指令(directive)来封装一系列的DOM操作,这样做非常方便。一般来说,指令是使用动态指令参数来获取App中的数据。

但是有些时候,自定义指令需要更多的数据来完成更复杂的功能,例如在指令中调用当前App实例的nextTick方法,以确保所有DOM元素加载完成,再进行DOM操作。还有一些情况,我们需要将一些全局配置参数传递给指令,已有的参数专递方式,显然无法满足这些需求。

本文介绍一种扩展指令参数的方法,使其可以接收更多参数。该方法在Vue 2.0和 Vue 3.0中,都可以正常使用。

基本原理

本文介绍的指令扩展方法,主要以闭包为基础,并且使用了一些函数参数柯里化的方式来管理多个参数的传递过程。

我们以Vue2.0的指令定义方式为例,说明基本原理。本文所使用的指令定义方式,都已基于插件化的定义方式,在main.js中,通过use方法使用。

示例代码如下:

const myDirective = {
    install(app,options){
        app.directive("img-load", {
            bind:function(el,binding,vnode){ },
            inserted:function(el,binding,vnode){ },
            update:function(el,binding,vnode){ },
            componentUpdated:function(el,binding,vnode){ },
            unbind:function(el,binding,vnode){ },
        });
    }
};
export default myDirective ;

按照上述标准的指令定义方式,无论使用哪个钩子函数,我们只能传递三个参数,指令所绑定的DOM元素,指令接收的APP中绑定参数和虚拟节点。

基于闭包的扩展方案

指令的钩子函数参数已经固定,我们无法修改。但是我们可以通过闭包设置钩子函数的作用域,让闭包函数来接收更多参数。

代码如下: 

export default function getMyDirective(Vue) {
    return class MyDirective{
        constructor(options) {
            this.options = options;
            this.bindDirective= this.bindDirective.bind(this);
        }
        bindDirective(el, bindings) {                        
        }
    }
}
const myDirective = {
    install(app,options){
         const DirectiveClass = getMyDirective(app) ;
        var myDirective = new DirectiveClass(options);
        app.directive("my-dirctive", {
            bind:myDirective.bindDirective
        });
    }
};
  • 使用闭包函getMyDirective来包裹钩子函数bindDirective
  • 闭包函数是用户自定义函数,我们可以设置任意多个参数
  • 在闭包函数中定义类来封装指令的所有操作,构造方法也可以接收参数,从而将多个参数柯里化分割。
  • 通过bind方法强行将指令钩子函数绑定的bindDirective方法的this限定为MyDirective的实例,也就是说,bindDirective方法可以通过this访问更多的数据。

JS中函数具有独立作用域,所以指令的绑定方法bindDirective在执行过程中,可以在不受任何外界其他代码的干扰下,使用闭包函数传递的参数。

实例和代码实现

本文以一个图片自动加载的指令为例,介绍自定义指令的参数扩展方式。

自定义指令的基本功能是根据图片的URL地址加载并显示图片,具体实现包括:

  • 通过指令动态参数获取图片地址
  • 首先在页面中显示一个正在加载的图片
  • 加载指定地址图片,如果加载成功,正常显示
  • 加载失败,显示一张加载出错的图片

本文以自顶向下的方式来介绍该实例的代码实现

Main.js中将指令对应的插件全局化

使用use方法,在全局定义插件ImageLoad,该插件主要是功能是在全局定义一个图片加载指令,为该指令接收一个全局配置,即加载中图片地址和加载失败的图片地址。

Vue.use.use(ImageLoad, {
  loading: "http://localhost:4000/images/loading.gif",
  error: "http://localhost:4000/images/error.jpeg",
});

ImageLoad插件定义

ImageLoad插件和其他插件一样,既然要通过use使用,所以要定义install方法,install方法的第一个参数是当前App实例,第二个则是指令的全局配置。

import getImageLoad from './getImageLoad'
const ImageLoad = {
    install(app,options){
        const ImgClass = getImageLoad(app) ;
        var loadImage = new ImgClass(options);
        app.directive("img-load", {
            bind: loadImage.bindImage
        });
    }
};
export default ImageLoad;
  • install方法中,首先通过调用getImageLoad方法,获取加载图片的管理类,传入当前App实例。
  • 实例化图片加载管理类的对象loadImage ,传入图片加载的全局配置。
  • 定义自定义指令v-img-load,该指定的bind钩子方法指向loadImage中的bindImage方法。
  • bindImage方法的this是指向loadImage对象,因此可以使用到App实例,指令全局配置,loadImage对象内的数据。

图片加载管理类的定义

ImageLoadManagement定义了v-img-load指令的全部实现。

export default function getImageLoad(Vue) {
    return class ImageLoadManagement {
        constructor(options) {
            this.options = options;
            this.bindImage = this.bindImage.bind(this);
            this.renderImage = this.renderImage.bind(this);
        }
        bindImage(el, bindings) {
            const self = this;
            Vue.nextTick(function(){
                const class="lazy" data-src = bindings.value;
                self.renderImage('loading', class="lazy" data-src, el);
                self.loadImage(class="lazy" data-src).then(
                    () => self.renderImage('', class="lazy" data-src, el),
                    () => self.renderImage('error', class="lazy" data-src, el),
                );
            });
            
        }
        loadImage(class="lazy" data-src) {
            return new Promise((resolve, reject) => {
                const img = new Image();
                img.class="lazy" data-src = class="lazy" data-src;
                img.onload = resolve;
                img.onerror = reject;
            });
        }
        renderImage(type, class="lazy" data-src, el) {
            let _class="lazy" data-src;
            const {
                error,
                loading
            } = this.options;
            switch (type) {
                case 'loading':
                    _class="lazy" data-src = loading;
                    break;
                case 'error':
                    _class="lazy" data-src = error;
                    break;
                default:
                    _class="lazy" data-src = class="lazy" data-src;
                    break;
            }
            el.setAttribute("class="lazy" data-src", _class="lazy" data-src);
        }
    }
}

为了避免参数过多,所以采用柯里化的方法,对参数进行了分割:

  • 在闭包函数getImageLoad中,定义了全局App实例参数;
  • ImageLoadManagement 类的构造方法中定义了图片加载指令需要的全局配置参数。
  • class 作为function的语法糖使用,其本质来时function,从而实现独立作用域。
  • bindImage方法中可以直接使用App实例的nextTick,无论该指令在父组件还是子组件中使用,都可以保证在指令中代码执行时,所有DOM元素加载完成。
  • loadImage方法用于检查指定URL的图片是否存在,如果存在则显示具体图片,否则则显示加载失败的图片。
  • renderImage方法用于设置指令绑定的Img元素的图片地址,图片的实际地址可以通过bindings参数的value属性获取。

通过上述方法,我们不仅扩展了指令的参数,使其可以支持更复杂的业务逻辑。

更重要的是。我们实现了指令的定义和实现逻辑的解耦,完全不再需要将所有的指令实现逻辑全部放在指令的注册方法中。通过ImageLoadManagement 的定义,将所有的指令实现逻辑都内聚在其中。

Vue 3.0的实现

Vue 3.0中,指令参数的扩展方法思路与2.0一致,只是因为Vue 3.0中指令的钩子函数名称与2.0不一致,造成一些区别。

具体代码如下:

import getImageLoad from './getImageLoad'
const ImageLoad = {
    install(app,options){
        const ImgClass = getImageLoad(options) ;
        var loadImage = new ImgClass();
        app.directive("img-load", {
            mounted: loadImage.bindImage
        });
    }
};
export default ImageLoad;

export default function getImageLoad(options) {
    return class ImageLoadManagement {
        constructor() {
            this.options = options;
            this.bindImage = this.bindImage.bind(this);
            this.renderImage = this.renderImage.bind(this);
        }
        bindImage(el, bindings) {
            const class="lazy" data-src = bindings.value;
            this.renderImage('loading', class="lazy" data-src, el);
            this.loadImage(class="lazy" data-src).then(
                () => this.renderImage('', class="lazy" data-src, el),
                () => this.renderImage('error', class="lazy" data-src, el),
            );
        }
        loadImage(class="lazy" data-src) {
            return new Promise((resolve, reject) => {
                const img = new Image();
                img.class="lazy" data-src = class="lazy" data-src;
                img.onload = resolve;
                img.onerror = reject;
            });
        }
        renderImage(type, class="lazy" data-src, el) {
            let _class="lazy" data-src;
            const {
                error,
                loading
            } = this.options;
            switch (type) {
                case 'loading':
                    _class="lazy" data-src = loading;
                    break;
                case 'error':
                    _class="lazy" data-src = error;
                    break;
                default:
                    _class="lazy" data-src = class="lazy" data-src;
                    break;
            }
            el.setAttribute("class="lazy" data-src", _class="lazy" data-src);
        }
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Vue的指令中实现传递更多参数

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Vue的指令中如何实现传递更多参数

本篇内容主要讲解“Vue的指令中如何实现传递更多参数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue的指令中如何实现传递更多参数”吧!基本原理本文介绍的指令扩展方法,主要以闭包为基础,并且使
2023-06-30

Vue在自定义指令绑定的处理函数中传递参数

这篇文章主要介绍了Vue在自定义指令绑定的处理函数中传递参数方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-03-10

VUE怎么实现路由传递参数

本篇内容介绍了“VUE怎么实现路由传递参数”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在路由时传递参数,一般有两种形式,一种是拼接在url
2023-07-04

iOS开发中怎么实现多参数传递

在iOS开发中,可以通过以下几种方式实现多参数传递:1. 使用NSDictionary或NSMutableDictionary:将多个参数封装到字典中,然后将字典作为参数进行传递。使用字典的好处是可以灵活地添加、删除或修改参数。```obj
2023-09-14

Vue怎么在自定义指令绑定的处理函数中传递参数

这篇文章主要介绍“Vue怎么在自定义指令绑定的处理函数中传递参数”,在日常操作中,相信很多人在Vue怎么在自定义指令绑定的处理函数中传递参数问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Vue怎么在自定义指令
2023-07-05

如何用vue实现组件间参数传递

这篇文章主要介绍“如何用vue实现组件间参数传递”,在日常操作中,相信很多人在如何用vue实现组件间参数传递问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何用vue实现组件间参数传递”的疑惑有所帮助!接下来
2023-07-04

Vue通过路由实现页面间参数的传递

这篇文章主要介绍了Vue通过路由实现页面间参数的传递,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-05-17

PHP 函数调用中的参数传递指南

php 函数调用中,参数传递包括按值传递、按引用传递和默认参数。按值传递复制变量值,按引用传递修改原始变量,默认参数提供预定义值。实战案例演示了按值传递计算税额、按引用传递交换变量和使用默认参数创建帖子。PHP 函数调用中的参数传递指南在
PHP 函数调用中的参数传递指南
2024-04-16

vue跳转页面和参数传递怎么实现

本篇内容介绍了“vue跳转页面和参数传递怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!要实现一个功能:从页面A跳转到页面B,并且页面
2023-06-30

如何传递 C++ 函数中的指针参数

指针参数用于在 c++++ 函数之间传递函数地址,以及用作实际参数。语法:returntype functionname(datatype *parametername); 例如,求和函数 sumarray 接受数组指针参数 arr 并返回
如何传递 C++ 函数中的指针参数
2024-04-20

Android 中怎么实现Activity 间传递参数

这篇文章将为大家详细讲解有关Android 中怎么实现Activity 间传递参数,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1.传递简单数据在A Activity中findViewByI
2023-05-30

Vue实现带参数的自定义指令示例

这篇文章主要为大家介绍了Vue实现带参数的自定义指令示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-01-11

编程热搜

目录