vue自定义指令

123 阅读3分钟

1.0 局部注册

vue 自带的指令比如 v-for v-bind v-click等,但是,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。

我们来写一个防止重复点击的指令

新建文件views/directive/test1.vue

<template>
  <div>
    <button v-no-more-click @click="clickHandle()">点我呀</button>
  </div>
</template>

<script>
export default {
  directives: {
    noMoreClick: {
      // 指令的定义
      inserted(el,binding) {
        el.addEventListener('click', (e) => {
          // 针对button的
          if (!el.disabled) {
            el.disabled = true;
            setTimeout(() => {
              el.disabled = false;
            }, binding.value || 2000)
          }
        })
      }
    }
  },
  data() {
    return {
      msg:'111'
    }
  },
  created() {
  },
  methods: {
    clickHandle(){
      console.log('1111')
    }
  }
}
</script>

你会发现点击之后 两秒之后才可以点击下一次,这就有效的防止了重复点击,当然了时间什么的我们是可以修改的比如

<button v-no-more-click="600" @click="clickHandle()">点我呀</button>

其中的inserted是钩子函数,还有几个

钩子函数

一个指令定义对象可以提供如下几个钩子函数 (均为可选):

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

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

  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。

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

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

2.0 全局注册

我们发现刚才的那个按钮 很多页面都用到了,所以就要全局注册啦,要不然每个页面我都在本页面注册一下,就很不美观,很不优雅。

新建文件 /src/until/directive/noMoreClik/index.js

export default (Vue) => {
    Vue.directive('noMoreClick', {
        inserted(el,binding) {
            el.addEventListener('click', (e) => {
                // 针对button的
                if (!el.disabled) {
                    el.disabled = true;
                    setTimeout(() => {
                        el.disabled = false;
                    }, binding.value || 2000)
                }
            })
        }
    })
}

main.js中注册

//... 省略
import noMoreClick from './until/no-more-click'

Vue.use(noMoreClick)
//... 省略

然后修改我们的test1.vue文件

<template>
  <div>
    <button v-no-more-click @click="clickHandle()">点我呀</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      msg:'111'
    }
  },
  created() {
  },
  methods: {
    clickHandle(){
      console.log('1111')
    }
  }
}
</script>

我们会发现效果是刚刚的

3.0 模拟权限指令

注意是模拟哦:后续我会出一篇权限控制的文章那时候可是会仔细的讨论这个权限的指令的

新增文件 /src/until/directive/auth/index.js

export default (Vue) => {
    Vue.directive('auth', {
        inserted(el,binding) {
            let rules = true; //
            let canShowList = ['admin','power','adminPower'];// 定义这三个可以看到
            if(binding?.value){ // 如果有值就处理
                rules = canShowList.includes(binding.value)
            }
             if (!rules) { // 制裁元素
                if (!el.parentNode) {
                    el.style.display = 'none'
                } else {
                    el.parentNode && el.parentNode.removeChild(el);
                }
            }
        }
    })
}

main.js中注册

import noMoreClick from './until/directive/noMoreClik/index.js'
import auth from './until/directive/auth/index.js'

Vue.use(noMoreClick)
Vue.use(auth)

修改 views/directive/test1.vue文件

<template>
  <div>
    <button v-no-more-click @click="clickHandle()">点我呀</button>
    <div v-auth="'admin'">我是admin</div>
    <div v-auth="'user'">我是user</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      msg:'111'
    }
  },
  created() {
  },
  methods: {
    clickHandle(){
      console.log('1111')
    }
  }
}
</script>

查看页面我们发现 我是user这个div没有显示出来,那就大功告成了

然后我们继续 添加指令,比如点击复制文本的指令..

重复我们上面的步骤,修改main的js.. 麻烦死啦,我就不能只注册嘛?

当然可以啦,好不容易你都看到这里了,怎么会让你失望呢!

4.0 自动注册自定义指令

我们修改两个页面

1.0 /src/until/directive/auth/index.js

const auth = (el,binding) => {
        let rules = true; //
        let canShowList = ['admin','power','adminPower'];// 定义这三个可以看到
        if(binding?.value){ // 如果有值就处理
            rules = canShowList.includes(binding.value)
        }
         if (!rules) { // 制裁元素
            if (!el.parentNode) {
                el.style.display = 'none'
            } else {
                el.parentNode && el.parentNode.removeChild(el);
            }
        }
}
export default auth

2.0 /src/until/directive/noMoreClick/index.js

 const noMoreClick =  (el,binding) => {
        el.addEventListener('click', (e) => {
            // 针对button的
            if (!el.disabled) {
                el.disabled = true;
                setTimeout(() => {
                    el.disabled = false;
                }, binding.value || 2000)
            }
        })
}
export default noMoreClick

新建页面 /src/until/directive/directive.js

/* 参数
*  directory:表示检索的目录;
*  useSubdirectories:表示是否检索子文件夹;
*  regExp:匹配文件的正则表达式,一般是文件名;
* */
const filesDirective = require.context('./', true, /index.js$/); // 检索已index.js结尾的文件
export default {
    install(vue) {
        filesDirective.keys().forEach(key => {
            // 遍历注册 
            vue.directive(files(key).default.name,files(key).default)
        })
    }
}

修改main.js

// import noMoreClick from './until/directive/noMoreClik/index.js'
// import auth from './until/directive/auth/index.js'
import directive from  './until/directive/directive.js'

// Vue.use(noMoreClick)
// Vue.use(auth)
Vue.use(directive)

项目重启,我们就可以用啦,跟之前一抹抹一样,以后如果还需要添加指令,只需要在 /until/directive/ 文件夹下面新建文件外对应的index.js就可以了,这看起来多干净,优雅

更多精彩请参考官方文档

保持心中的那束光,未来有人会借它穿过黑暗

qdysh.png