Vue.js自定义指令

除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。举个聚焦输入框的例子,如下:

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

然后你可以在模板中任何元素上使用新的 v-focus 属性,如下:

<input v-focus>

钩子函数

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置

inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。

componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

unbind:只调用一次,指令与元素解绑时调用

接下来我们来看一下钩子函数的参数 (即 elbindingvnode 和 oldVnode)。

  • el:指令所绑定的元素,可以用来直接操作 DOM 。
  • binding:一个对象,包含以下属性:
    • name:指令名,不包括 v- 前缀。
    • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
    • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
    • expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"
    • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"
    • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }
  • vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
  • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

举两个实际的例子:

图片的懒加载,默认在图片加载之前给容器设置一个随机色,然后图片加载完以后赋值给容器的背景图片(或者给容器里面的img的src赋值)

        <style>
            .imgwraps{
                height: 200px;
                width: 200px;
                background-position: center center;
            }
        </style>

    <div id="app">
        <div class="imgwraps" v-for="item in lists" v-img="item.url">
            <!-- <img src="" alt=""> -->
        </div>    
    </div>

        <script>
            Vue.directive('img',{
                inserted:function(el,binding){
                    var color=Math.floor(Math.random()*1000000);
                    // var target=el.getElementsByTagName('img')[0];
                    el.style.background='#'+color;   // 设置随机背景色
                    var img= new Image();
                    img.src=binding.value;          // 获取绑定到指令上面的值
                    img.onload=function(){
                        el.style.backgroundImage="url("+ binding.value +")";
                        // target.src=binding.value;
                    }
                }
            })
            new Vue({
                el:'#app',
                data:{
                    lists:[
                        {url:'1.jpg'},
                        {url:'2.jpg'},
                        {url:'3.jpg'}
                        ]
                    }
                })
    </script>

 

用自定义指令实现一个常见的 tip 提示弹框的功能,鼠标移入元素,可以在元素的上下左右显示 tip,鼠标移出则隐藏 tip

 

 

<style>
        li{
            list-style: none;
            width: 100px;
            height: 100px;
            border:1px solid #eee;
            position: relative;
        }
        li:hover{
            background: red;
        }
        .tips{
            position: absolute;
            width: 100px;
            height: 50px;
            background: #000;
            color: #fff;
            text-align: center;
        }
        .tips.left{
            left: 130px;
            top: 25px;
        }
        .tips.right{
            right: 130px;
            top: 25px;
        }
        .tips.top{
            left: 50%;
            margin-left: -50px;
            top: -75px;
        }
        .tips.bottom{
            left: 50%;
            margin-left: -50px;
            bottom: -75px;
        }
        .tips:after{
            position: absolute;
            border:10px solid transparent;
            content: "";
        }
        .left:after{
            border-right-color: #000;
            left: -20px;
            top: 50%;
            margin-top: -10px;
        }
        .right:after{
            border-left-color: #000;
            right: -20px;
            top: 50%;
            margin-top: -10px;
        }
        .bottom:after{
            border-bottom-color: #000;
            top: -20px;
            left: 50%;
            margin-left: -10px;
        }
        .top:after{
            border-top-color: #000;
            bottom: -20px;
            left: 50%;
            margin-left: -10px;
        }</style>

    <div id="app">
        <ul>
            <!-- 可支持设置top,bottom,left,right四个方向 -->
            <li v-mytip.top="mes">sss</li>
        </ul>   
    </div>

    <script>
            Vue.directive('mytip', {
                  bind: function (el, binding, vnode) {
                  var flag=false;
                  el.onmouseover=function(){
                      if (!flag) {
                      var newEle=document.createElement("div");
                      newEle.id="tip";
                      newEle.className='tips '+Object.keys(binding.modifiers);  // 一个包含修饰符的对象,这里主要用获取tops的展示
                      newEle.innerHTML=binding.expression; //字符串形式的指令表达式
                      el.append(newEle);
                         flag=true; 
                    } 
                  } 
                 el.onmouseout=function(){ 
                    document.getElementById('tip').remove(); flag=false; 
                } 
             }
           })
    new Vue({ el:'#app', data:{ mes:'hahahahah' } }) </script>
 

 

select指令

<article>
<h1 class="header red">Vue.js Custom Directive with Semantic-UI Dropdown</h1>
<div class="ui divider"></div>
<div id="el">
<select v-select="selected">
<option value="">default</option>
<option v-for="option in options" v-bind:value="option.id">
{{ option.text }}
</option>
</select>
<div class="ui divider"></div>
<span>Selected Key : {{ selected }}</span>
</div>

</article>

Vue.directive('select', {
  twoWay: true,
  priority: 1000,


  params: ['options'],
    
  bind: function () {
    var self = this
    $(this.el)
      .dropdown({
        onChange: function(value) {
            //alert(value)
      self.set(this.value)
    }
      })
  },
  update: function (value) {
    console.log(value);
  }
})




var vm = new Vue({
  el: '#el',
  data: {
    selected: 0,
    options: [
      { id: 1, text: 'Hello' },
      { id: 2, text: 'Bonjour' },
      { id: 3, text: 'Salam' }
    ]
  },
  watch: {
  'selected': function (val, oldVal) {
    //alert('Parent --> new value is :'+ this.options[val-1].text);
    }
  }  
    

})

 

最大的字符数限制的指令

<div id="root" class="container">
  <h2>You can type only 10 characters</h2>
  <textarea v-maxchars="10" cols="50" rows="5"></textarea>

</div>

var maxchars = Vue.directive("maxchars", {
  bind: function(el, binding, vnode) {
    var max_chars = binding.expression;
    var handler = function(e) {
      if (e.target.value.length > max_chars) {
        e.target.value = e.target.value.substr(0, max_chars);
      }
    };
    el.addEventListener("input", handler);
  }
});


var app = new Vue({
    el: '#root'
});

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值