Vue自定义指令和自定义过滤器

一、自定义指令:

自定义指令分为两种:全局自定义指令和局部自定义指令

全局指令指所有组件都可以使用,局部指令是只有在当前组件中才可以使用。

如,我们现在有个需求,当一个输入框获取焦点时,显示出一个div框,且可点击使之变色,当我们点击div框之外的地方,隐藏弹出的div框

<div v-click-outside="hide">
    <input type="text" @focus="show">
    <div v-if="isShow" style="width: 100px; height:100px;background: red;" @click="changeColor"></div>
</div>

vue实现方式如下:

let vm = new Vue({
    el:"#app",
    data(){
        return{
            isShow:false,
        }
    },
    methods:{
        show(){
            this.isShow = true;
        },
        changeColor(e){
            let c = [0,1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'];
            let r = "#";
            for(let i=0;i<c.length;i++){
                r += c[Math.floor(Math.random()*c.length)];
            }
            e.target.style.background=r;
        }
    },
    directives:{
        'click-outside'(el,bindings,vnode){
            document.addEventListener("click",function test(e){
                if(!el.contains(e.target)){
                    vnode.context[bindings.expression]();
                    document.removeEventListener("click",test);
                }
            })
        }
    }
});

 上面自定义了一个简单的局部指令,指令函数有三个参数

el:当前dom节点,初始化div默认是不展示的:

bingings:当前节点所有绑定的属性:

  name:指令名字

  value:指令的绑定值

  expression:字符串形式的指令表达式

  oldValue:指令绑定的前一个值(仅在update 和 componentUpdated 钩子中可用)

  arg:传给指令的参数(可选)

vnode:虚拟节点,它的上下文context里面有所有当前Vue对象上绑定的属性和方法

再看一个需求:有一个输入框,界面一刷新,输入框就会自动获得焦点。这个需求看起来很简单,但是这里涉及到了一个钩子的生命周期问题

<input type="text" v-focus="focus" />

Vue.directive("focus",function(el, bindings, vnode){
    el.focus()
})

上面是最直观想到的方案,但是在实际执行过程中发现,这种做法是无效的。为什么呢?先看下自定义指令的生命周期:

自定义指令默认有5个生命周期:bind, inserted, update, componentUpdated, unbind

  bind::在指令第一次绑定到元素时调用。只会执行一次,且此时dom元素还没有插入页面父节点

  inserted:被绑定元素插入到父节点时调用

  update:被绑定元素所在模板更新时调用,无论绑定值是否变化

  componentUpdated:被绑定元素所在模板完成一次更新时调用

  unbind:指令解绑时调用,也只会执行一次

看了上面的指令生命周期,再看说我们上面的自定义指令为何不能成功?原因是组件在初始化调用指令时,是在bind中调用的,而这时dom元素还没有插入到父节点。

正确的应该怎么实现呢?

<input type='text' v-focus="focus">

new Vue({
    el:"app",
    directives:{
        'focus'(el, bindings, vnode){
            bind(){
                console.log("bind");
            },
            inserted(){
                el.focus()
            },
        }
    }
})

二、自定义过滤器

如,我们需要将用户英文名第一个字母大写,其他小写

使用方式 :{{ name | toUpper(1)  }}  // | :管道符

Vue.filter("toUpper",function(value, count){
    count = count?count:value.length-1
    return value.substr(0,count).toUpperCase()+value.substr(count);
});
    

附上Vue生命周期图

猜你喜欢

转载自www.cnblogs.com/fiona-zhong/p/11919148.html