Vue本身推崇数据驱动视图的理念,但并非所有情况都适合。自定义指令就是一种有效的补充和扩展。
解决:可复用的原生DOM的操作,集成第三方插件(jQ庞大的插件系统改造成支持vue)。
举两个实际的例子:
图片的懒加载,默认在图片加载之前给容器设置一个随机色,然后图片加载完以后赋值给容器的背景图片(或者给容器里面的img的src赋值)
<style> .imgwraps{ height: 200px; 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:'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1502715114297&di=840f123ee136494fc0512601f4ae4e14&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimage%2Fc0%253Dshijue1%252C0%252C0%252C294%252C40%2Fsign%3D4e3e0e04b4096b6395145613645aed31%2Ff7246b600c338744af80e6575b0fd9f9d72aa050.jpg'}, {url:'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1502715142264&di=b1e6cee1f9d4ed8b4227ad93ee3260c9&imgtype=0&src=http%3A%2F%2Fpic.58pic.com%2F58pic%2F12%2F29%2F68%2F12558PICryv.jpg'}, {url:'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1502715160553&di=65bf398e977d41d0d0b7e02e8400b846&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimage%2Fc0%253Dshijue1%252C0%252C0%252C294%252C40%2Fsign%3D5552aa402f2dd42a4b0409e86b5231c0%2F2934349b033b5bb54b92dfd73cd3d539b600bc56.jpg'} ] } }) </script>
用自定义指令实现一个常见的 tip 提示弹框的功能,鼠标移入元素,可以在元素的上下左右显示 tip,鼠标移出则隐藏 tip
<style> li{ list-style: none; 100px; height: 100px; border:1px solid #eee; position: relative; } li:hover{ background: red; } .tips{ position: absolute; 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); 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>