Vue2基础 14:自定义指令

1 函数式

1.1 案例–v-text放大10倍

<body>
    <div id="root">
        <h2>当前的n值是:<span v-text="n"></span></h2>
        <h2>放大10倍的n值是:<span v-big="n"></span></h2>
        <button @click="n++">点我n+1</button>
    </div>
</body>

<script type="text/javascript">
    new Vue({
        el:'#root',
        data:{
            n:1,
        },
        
        // --------定义一个全新的配置项----------
        directives:{
            //big:function(){} 简写如下
            big(element,binding ){
                element.innerText = binding.value * 10
            }
            //big函数被调用的情况:
            //1.指令与元素成功绑定时(初次)
            //2.指令所在的模板(div id ="root")重新解析时
        }
    })
</script>

innerText: 返回或设置元素中的纯文本内容,只适用于IE/Chrome

  • big函数收到的是两个参数:第一个是真实DOM
  1. 判断方法一
    big(a,b){ console.dir(a) }
    控制台输出了真实DOM身上所有的属性和方法
    在控制台的输出

补充:

  1. console.dir()console.log()的区别
  2. MDN上console:dir() 静态方法的介绍
  1. 判断方法二
    big(a,b){ console.log(a instanceof HTMLElement) }
    检测a是不是HTMLElement的实例,输出为true

MDN上instanceof的定义instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
即:
在左边的检测对象的原型链上面查找右边的构造函数的prototype属性是否出现,这个过程会沿着原型链一直找,直到找到原型链的最顶端Object.prototype还没找到,那就只能返回null了,说明该对象不是这个构造函数的实例.

  • big函数收到的是两个参数:第二个是个对象,且含有指令后面代数式的值、指令的名字、使用时指令的名字
    console.log(b)

2 对象式

2.1 案例–v-fbind默认获取焦点(函数式)

先通过案例来看一下,函数式写法会有什么问题。

<body>
    <div id="root">
        <h2>当前的n值是:<span v-text="n"></span></h2>
        <input type="text" v-fbind:value="n">
        <button @click="n++">点我n+1</button>
    </div>
</body>

<script type="text/javascript">
    new Vue({
        el:'#root',
        data:{
            n:1,
        },
        //--------定义一个全新的配置项-----------
        directives:{
            fbind(element,binding ){
                element.value = binding.value
                element.focus()
            }
        }
    })
</script>

存在问题:
运行后没有获取焦点,点击按钮才有焦点。
原因:

  1. 按照顺序 指令与元素绑定页面编译 之前。
  2. 那么函数的第一次调用是指令与元素成功绑定时,是在页面上呈现input之前。
  3. 但是模板是经过vue编译才放在页面上的,绑定在编译之前,而在input出现在页面之前是无法获取焦点的。

点击按钮,n值修改,模板重新解析,重新调用指令fbind,现在input元素已在页面上,所以获取焦点。

此时fbind指令是函数形式,调用只存在以下两个时机:

  1. 指令与元素成功绑定时(初次)
  2. 指令所在的模板重新解析时

区分: span.innerText | input.value

2.2 案例–v-fbind默认获取焦点(对象式)

<body>
    <div id="root">
        <h2>当前的n值是:<span v-text="n"></span></h2>
        <input type="text" v-fbind:value="n">
        <button @click="n++">点我n+1</button>
    </div>
</body>

<script type="text/javascript">
    new Vue({
        el:'#root',
        data:{
            n:1,
        },
        //--------------定义一个全新的配置项-------------
        directives:{
            fbind:{
            //以下函数都是固定的且常用的:
                //指令与元素成功绑定时调用
                bind(element,binding){
                    //此时可以写:样式、value值、绑定事件
                    input.value = binding.value
                },
                //指令所在元素被插入页面时
                inserted(element,binding){
                    element.focus()
                },
                //指令所在的模板重新解析时
                update(element,binding){
                     input.value = binding.value
                     element.focus()
                }
            }
        }
    })
</script>

bind和update函数的逻辑往往是一致的,所以也就有了函数式指令,因此如果没有其他特殊要求(获取焦点、拿到父元素),可以用函数式。

3 自定义指令容易犯的错

  1. 指令命名多个词用-连接(kebab-case),而不是写成驼峰命名法(camelCase),且directives配置项需要加‘’,定义时不加v-,但是使用时需要加。
    例如定义一个input元素的指令
    <input type="text" v-bigNumber:value="n">
    应写成
    <input type="text" v-big-number:value="n">
    对应Vue实例中配置项的函数式:
    'big-number'(){}
    实际上big-number为directives对象里的key,当出现-时不可简写
  2. 指令相关的回调函数的this不是vm而是Window
    console.log('fbind',this)
    输出为window
  3. 自定义指令为局部指令,只给有定义的vue实例使用
    即使用的模板的<div>中的id 和Vue实例中的el相对应
<script type="text/javascript">
    //对象式
    new Vue({
        directives:{
            指令名:{配置对象}
        }
    })//函数式
    new Vue({
        directives:{
            指令名(参数1,...){
                回调函数
            }
        }
    })
</script>

4 全局指令写法(参考过滤器写法):

  • 对象式:
<script type="text/javascript">
Vue.directive('fbind',{
     bind(element,binding){
        input.value = binding.value
     },
    inserted(element,binding){
        element.focus()
    },
    update(element,binding){
        input.value = binding.value
        element.focus()
    }
})
</script>
  • 函数式
<script type="text/javascript">
Vue.directive('fbind',function(element,binding){
    element.value = binding.value
    element.focus()
})
</script>
  • 24
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值