美文网首页
Vue中 directive 用法

Vue中 directive 用法

作者: HHHHy2019 | 来源:发表于2020-04-19 23:38 被阅读0次

directive的官方文档

Vue.directive( id, [definition] )

  • 参数

    • {string} id
    • {Function | Object} [definition]
  • 用法

    注册或获取全局指令。

    // 注册
    Vue.directive('my-directive', {
      bind: function () {},
      inserted: function () {},
      update: function () {},
      componentUpdated: function () {},
      unbind: function () {}
    })
    
    // 注册 (指令函数)
    Vue.directive('my-directive', function () {
      // 这里将会被 `bind` 和 `update` 调用
    })
    
    // getter,返回已注册的指令
    var myDirective = Vue.directive('my-directive')
    
  • 案例:

<html>
  <head>
    <title>directive 用法</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="root">
      <div v-loading="isLoading">{{data}}</div>
      <button @click="update">更新</button>
    </div>
    <script>
      Vue.directive('loading', {
        //当我们的isLoading发生变化的时候会触发update
        //1. 传入的是object
        update(el, binding, vnode) {
          // 会触发两次
          console.log(el, binding, vnode)
          /*
          第一次调用:
          <div></div>
          {name: "loading", rawName: "v-loading", value: true, expression: "isLoading", modifiers: {…},name: "loading",oldArg: undefined,oldValue: false,rawName: "v-loading",value: true, …} 
          VNode {tag: "div", data: {…}, children: Array(1), text: undefined, elm: div, …}
          第二次调用:
          <div>用户数据 </div> 
          {name: "loading", rawName: "v-loading", value: false, expression: "isLoading", modifiers: {…},name: "loading",oldArg: undefined,oldValue: true,rawName: "v-loading",value: false, …} 
          VNode {tag: "div", data: {…}, children: Array(1), text: undefined, elm: div, …}
          */
          if (binding.value) {
            // 非侵入的创建一个遮罩,可以封装成固定的静态组件
            const div = document.createElement('div')
            div.innerText = '加载中...'
            div.setAttribute('id', 'loading')
            div.style.position = 'absolute'
            div.style.left = 0
            div.style.top = 0
            div.style.width = '100%'
            div.style.height = '100%'
            div.style.display = 'flex'
            div.style.justifyContent = 'center'
            div.style.alignItems = 'center'
            div.style.color = 'white'
            div.style.background = 'rgba(0, 0, 0, .7)'
            document.body.append(div)
          } else {
            document.body.removeChild(document.getElementById('loading'))
          }
        },
      })
      /*
      2.传入的是function
       Vue.directive('loading', {
        update(el, binding, vnode) {
          console.log(el, binding, vnode)
          if (binding.value) {
            const div = document.createElement('div')
            div.innerText = '加载中...'
            div.setAttribute('id', 'loading')
            div.style.position = 'absolute'
            div.style.left = 0
            div.style.top = 0
            div.style.width = '100%'
            div.style.height = '100%'
            div.style.display = 'flex'
            div.style.justifyContent = 'center'
            div.style.alignItems = 'center'
            div.style.color = 'white'
            div.style.background = 'rgba(0, 0, 0, .7)'
            document.body.append(div)
          } else {
            // 因为是function时会直接绑定到bind和update两个生命周期上,当时bind时,我们的loading还没有加入当页面当中,所以会找不到这个dom节点
            const div = document.getElementById('loading')
            div && document.body.removeChild(div)
          }
        },
      })
      */

      new Vue({
        el: '#root',
        data() {
          return {
            isLoading: false,
            data: '',
          }
        },
        methods: {
          update() {
            this.isLoading = true
            setTimeout(() => {
              this.data = '用户数据'
              // 获取请求时我们可以使用try catch方法防止未知错误
              this.isLoading = false
            }, 3000)
          },
        },
      })
    </script>
  </body>
</html>


  • directive的源码
//vue.js:5210

function initAssetRegisters(Vue) {
  /**
   * Create asset registration methods.
   */
  ASSET_TYPES.forEach(function (type) {
    //type => directive
    Vue[type] = function (id, definition) {
      //id => "loading",definition = >{update:f}
      if (!definition) {
        return this.options[type + 's'][id]
      } else {
        /* istanbul ignore if */
        if (type === 'component') {
          validateComponentName(id)
        }
        if (type === 'component' && isPlainObject(definition)) {
          definition.name = definition.name || id
          definition = this.options._base.extend(definition)
        }
        if (type === 'directive' && typeof definition === 'function') {
          //我们的definition是object
          definition = { bind: definition, update: definition } //如果是function,直接添加到bind和update这两个生命周期上
        }
        this.options[type + 's'][id] = definition //this.options.directives.loading = f
        /*
        =>
        options:{
          components: {KeepAlive: {…}, Transition: {…}, TransitionGroup: {…}}
          directives:{
            loading: {update: ƒ}
            model: {inserted: ƒ, componentUpdated: ƒ}
            show: {bind: ƒ, update: ƒ, unbind: ƒ}
          }
          filters: {}
          _base: ƒ Vue(options)
        }
        */
        return definition
      }
    }
  })
}

相关文章

网友评论

      本文标题:Vue中 directive 用法

      本文链接:https://www.haomeiwen.com/subject/ltsgbhtx.html