【Vue2】自定义指令 directives & 过滤器 filter

自定义指令 directives

directives 的简写

  • 我们可以通过配置项 directives 来自定义指令
  • 自定义指令时直接写指令名 XXX,使用时需要加上前缀为 v-XXX
<div id="app">
    <!-- 使用自定义指令 big -->
    <div v-big="num"></div>
</div>
let vm = new Vue({
    el: "#app",
    data: { num: 1 },
    // 配置 directives
    directives: {
        // 配置 [注册函数]
        big(ele, binding, node) { // 接收 3 个参数
            // 参数1 - ele:挂载的 DOM 节点
            console.log("ele", ele); // ele div

            // 参数2 - binding:绑定对象
            console.log("binding", binding);
            // binding {name: 'big', rawName: 'v-big', value: 1, expression: 'num', …}

            // 参数3 - node:虚拟节点
            console.log("node", node);
            // node VNode {tag: 'div', data: {…}, children: undefined, text: undefined, elm: div, …}

            // this 指向 window
            console.log("this", this);

            // 操作 DOM
            ele.innerText = binding.value + " -> " + binding.value * 10;
        }
    }
});

指令的命名

  • 指令名为多个单词时,用 - 拼接
<!-- 使用自定义指令 my-instruction -->
<div v-my-instruction="value"></div>
let vm = new Vue({
    el: "#app",
    data: { value: 100 },
    directives: {
        "my-instruction"(ele, binding) {
            console.log("ele", ele); // ele div
            console.log("binding", binding);
            // binding {name: 'my-instruction', rawName: 'v-my-instruction', value: 100, …}
        }
    }
});

回调函数的触发

上面的 [注册函数] 是一种简写,触发的时间有两个:
①指令与元素绑定时触发、②模版重新渲染时触发(就是说,页面被重新渲染就会触发)

指令与元素绑定时触发注册函数,注册函数执行完后,虚拟 DOM 才插入到页面中
就是说,如果我们在注册函数中设置页面的动态效果 (eg: focus),是不会生效的:

姓名:<input type="text" v-model="name" v-focus>
<button @click="change">修改</button>
let vm = new Vue({
    el: "#app",
    data: { name: "superman" },
    directives: {
        focus(el) { el.focus(); } // DOM 元素调用 focus() 方法,实现聚焦功能
        // 但该 [注册函数] 执行完后,虚拟 DOM 才插入到页面中,所以聚焦功能并没有生效
    },
    methods: {
        // 修改 DOM 元素,使页面重新渲染 ( [注册函数] 再被调用 )
        change() { this.name += "!" }
    }
});

我们可以发现,在页面加载完成后,input 元素并没有聚焦。之后修改 data 中的数据后,页面重新渲染,input 才聚焦
(修改 data 中的数据,页面重新渲染,注册函数再被调用,再次执行 focus(),input 才会聚焦)


directives 的标准写法

  • 简写中,注册函数只能在 [指令与元素绑定]、[模版被重新渲染] 时触发
  • 如果使用标准写法,通过钩子函数,可以设置挂载元素在不同状态下的行为
  • 注意:每个钩子函数都接收 elbindingvnode 3 个参数
focus: {
    bind() {
        console.log("指令与元素绑定时触发");
    },
    inserted(el) {
        console.log("指令所在元素插入页面时触发");
        el.focus();
    },
    update(el) {
        console.log("模板重新渲染时触发");
        el.focus();
    }
}

全局注册 directive

  • Vue.directive("自定义指令名", 配置对象) // 注意:全局注册的关键字是 directive,不是 directives
  • 注意:全局注册的话, Vue.directive() 需要在 Vue 实例创建之前编写
Vue.directive("focus", {
    bind() {
        console.log("指令与元素绑定时触发");
    },
    inserted(el) {
        console.log("指令所在元素插入页面时触发");
        el.focus();
    },
    update(el) {
        console.log("模板重新渲染时触发");
        el.focus();
    }
});

let vm = new Vue({
    el: "#app",
    data: { name: "superman" },
    methods: {
        change() { this.name += "!" }
    }
});
  • 也可以使用简写(回调函数执行完后,DOM 才会插入到页面中):
Vue.directive("focus", (el, binding) => {
    console.log(el, binding); // el:挂载的元素; binding:挂载的信息
    console.log(binding.value); // 获取指令的属性值
});



过滤器 filter (Vue3已弃用)

  • 一般用于格式化数据
dayjs
<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.4.1/dayjs.min.js"></script>
  • 引入 dayjs 后,暴露 dayjs 方法,接收 1 个时间戳参数,默认为当前时间戳
  • format 为格式化方法,接收字符串参数,为格式化的模版
dayjs().format('YYYY-MM-DD HH:mm:ss')

局部过滤器

  • 配置 filters 属性对象,该对象的属性值为过滤器方法
  • 局部创建的过滤器,只能在挂载对象内使用
<div id="app">
    time: {{time}} <br />
    <!-- 过滤器的书写格式:  被过滤的数据 | 过滤后的数据 -->
    fmtTime: {{time | fmtTime}}
</div>
let vm = new Vue({
    el: "#app",
    data: { time: 1648275087640 },
    filters: {
        // [被过滤的数据] 会作为第 1 参数传入
        fmtTime(time) {
            /* 引入 dayjs 后,暴露 dayjs 方法,接收 1 个时间戳参数,默认为当前时间戳 */
            /* format 为格式化方法,接收字符串参数,为格式化的模版 */
            return dayjs(time).format('YYYY-MM-DD HH:mm:ss')
        }
    }
});
带参数的过滤器
<!-- 管道可以配置参数 -->
fmtTime: {{time | fmtTime("YYYY_MM_DD")}}
filters: {
    // 配置的参数会作为后续参数传入,第 1 参数始终是 [被过滤的数据]
    fmtTime(time, fmtStr = "YYYY-MM-DD HH:mm:ss") {
        // 给 fmtStr 设置默认值
        return dayjs(time).format(fmtStr)
    }
}
过滤器的链式调用
time: {{time}} <br />
fmtTime: {{time | fmtTime}} <br />
<!-- 管道可以链式调用 -->
date: {{time | fmtTime | date}}
filters: {
    fmtTime(time, fmtStr = "YYYY-MM-DD HH:mm:ss") { return dayjs(time).format(fmtStr) ,
    date(time) { return time.split(' ')[0] }
}
配合 v-bind 使用,可以设置标签元素的属性值
<div :name="msg | prefix">{{msg | prefix}}</div>
let vm = new Vue({
    el: "#app",
    data: { msg: "superman" },
    filters: {
        prefix(val) { return val.slice(0, 5) },
    }
});
filter 可用 computed / methods 替代
time: {{time}} <br />
fmtTime: {{fmtTime}}
let vm = new Vue({
    el: "#app",
    data: { time: 1648275087640 },
    computed: {
        fmtTime() { return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss') }
    },
});

全局过滤器

Vue.filter(name, callback)
  1. name:自定义名称
  2. callback:回调函数,接收 1 个参数 val-被过滤的数据
  • 注意:全局注册的话,Vue.filter() 需在 Vue 实例创建之前编写
<input type="text" v-model="msg">
<!-- 使用过滤器格式化字符串,将首字母大写 -->
<h2>{{msg | upFirst}}</h2>
// 创建全局过滤器 - 默认 [被过滤的数据] 为第 1 参数
Vue.filter("upFirst", val => val.charAt(0).toUpperCase() + val.slice(1));

let app = new Vue({
    el: "#app",
    data: { msg: "superman" }
});
带参数的全局过滤器
<!-- 使用带参数的全局过滤器 -->
<h2>{{time | format('yyyy-MM-dd')}}</h2>
// 创建带参数的全局过滤器
Vue.filter("format", (val, arg) => { // 第 2 个形参开始,就是用于接收传入的参数的啦
    let res = '';
    if (arg == 'yyyy-MM-dd')
        res = val.getFullYear() + '-' + (val.getMonth() + 1) + '-' + val.getDate();
    return res;
});

let app = new Vue({
    el: "#app",
    data: { time: new Date() }
});



页面的渲染

  • data 中的数据更新后,页面会更新模板中的数据,重新渲染页面
  • 更新模板中的数据,参与数据显示的方法就会被调用
<div id="app">
    {{name}} ----- {{myName}} ----- {{showName()}} ----- {{name | changeName}}
</div>
Vue.filter("changeName", val => {
    console.log("filter");
    return val.charAt(0).toUpperCase() + val.slice(1);
});

let vm = new Vue({
    el: "#app",
    data: { name: "superman" },
    computed: {
        myName() {
            console.log("computed");
            return this.name
        }
    },
    methods: {
        showName() {
            console.log("methods-showName");
            return 123;
        },
        others() { // 该方法没有在页面上显示数据,所以渲染页面时不会调用该方法
            console.log("methods-others");
            return 345;
        }
    }
});
  • 初始化页面时,需要获取 data 中的数据 namecomputedmyName 返回的数据、methodsshowName 返回的数据、filter 的回调函数返回的数据
  • 如果修改了 data 中的数据 name,页面需要重新渲染,myNameshowName 等所有参与了数据显示的方法,都会再执行一次
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue.js 2中,自定义指令是一种扩展Vue实例功能的方式。根据引用,自定义指令可以分为组件私有自定义指令和项目全局自定义指令。组件私有自定义指令仅在特定组件中可用,而项目全局自定义指令可以在整个项目中使用。 自定义指令定义方式与过滤器定义方式类似。可以通过在Vue实例的directives选项中定义指令或在组件的directives选项中定义指令。具体的例子如引用所示,在任意组件中使用v-color指令。 在指令定义中,可以通过bind和update函数来实现指令所需的逻辑。bind函数在指令被绑定到元素时调用,可以进行初始化设置。update函数在指令所在元素的值发生变化时调用,可以响应数据的变化并做出相应的操作,如引用所述。 总结来说,Vue.js 2中的自定义指令是一种可以扩展Vue实例功能的方式,可以在组件私有或项目全局范围内使用。可以通过定义指令和实现相应的逻辑来实现自定义指令的功能。&lt;span class=&quot;em&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;em&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;em&quot;&gt;3&lt;/span&gt; #### 引用[.reference_title] - *1* *2* *3* [vue2自定义指令方式](https://blog.csdn.net/qq_40639028/article/details/120145794)[target=&quot;_blank&quot; data-report-click={&quot;spm&quot;:&quot;1018.2226.3001.9630&quot;,&quot;extra&quot;:{&quot;utm_source&quot;:&quot;vip_chatgpt_common_search_pc_result&quot;,&quot;utm_medium&quot;:&quot;distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1&quot;}}] [.reference_item style=&quot;max-width: 100%&quot;] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JS.Huang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值