一, 自定义指令:
自定义指令分为两种: 全局自定义指令和局部自定义指令
全局指令指所有组件都可以使用, 局部指令是只有在当前组件中才可以使用.
如, 我们现在有个需求, 当一个输入框获取焦点时, 显示出一个 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 生命周期图
来源: http://www.bubuko.com/infodetail-3319407.html