您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Vue 自定义指令

本小节我们介绍 Vue 中的指令。全局指令的、局部指令的、指令的使用以及动态指令传参。其中,指令和动态指令参数是本节的难点。

同学们需要充分理解每个指令执行的时机、对动态指令参数多加练习才能对指令的使用得心应手。

Vue 除了提供了认内置的指令外,还允许开发人员根据实际情况指令,它的作用价值在于当开发人员在某些场景下需要对普通 DOM 元素进行底层操作的时候。 – 官方定义

在之前的章节中我们学习了指令 v-show,他的实现原理就是操作 DOM 元素的样式 display,使之实现隐藏、的。在日常开发中,我们经常把一些对 DOM 大量相同的操作封装成指令。学好指令可以给我们的开发带来便利、提高效率。同学们需要总结业务中的各种场景,多加练习。

Vue 指令和组件一样存在着全局和局部两种方式。全局的指令可以在项目中的所有组件中使用,局部的指令只能在当前组件内部使用。接下来我们分步介绍全局指令和局部指令的方式。

我们可以通过 Vue.directive 的方式来定义全局指令, 它接收两个参数:1. 指令名,2. 指令的对象。
命名:

对象:指令的对象我们将在下面段落 4 中详细介绍。

注意:指令时,指令不需要加 v- 前缀,认是前缀的,使用指令的时候一定要 v- 前缀。

// 
// 驼峰命名
Vue.directive('MyDirective', {/* */})
// 短横线命名
Vue.directive('my-directive', {/* */})

// 使用
<div v-my-directive></div>

下面我们全局指令 v-focus,该指令的是在加载时,使得元素获得焦点。

<!DOCTYPE html>
<html lang="en">
<head>
  < charset="UTF-8">
  < name="viewport" content="width=device-width, initial-scale=1.0">
  < http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>
      <label>姓名:</label>
      <input id="name" v-focus type="text"/>
    </div>
    <div>
      <label>年龄:</label>
      <input id="age" type="text"/>
    </div>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
  Vue.directive('focus', {
    inserted(el) {
      el.focus()
    }
  })
  var vm = new Vue({
    el: '#app',
    data() {
    	return {}
    }
  })
</script>
</html>

解释:
JS 第 3-7 行,我们定义了指令 v-focus,定义 inserted ,在节点被插入时获得焦点。
HTML 第 4 行,我们在 input 元素上使用指令,当打开时 id 为 name 的输入框会焦点。

指令的局部和组件的局部类似,在实例的参数 options 中使用 directives 选项来局部指令,局部指令只能在当前这个实例中使用:

// 
// 短横线命名
{
  directives: {
      'my-directive': {
        inserted: function (el) {
          el.focus()
        }
      }
    }
}
// 驼峰命名
{
  directives: {
      'MyDirective': {
        inserted: function (el) {
          el.focus()
        }
      }
    }
}

// 使用
<div v-my-directive></div>
<!DOCTYPE html>
<html lang="en">
<head>
  < charset="UTF-8">
  < name="viewport" content="width=device-width, initial-scale=1.0">
  < http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>
      <label>姓名:</label>
      <input v-focus type="text"/>
    </div>
    <div>
      <label>年龄:</label>
      <input type="text"/>
    </div>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
  var vm = new Vue({
    el: '#app',
    data() {
    	return {}
    },
    directives: {
      focus: {
        inserted: function (el) {
          el.focus()
        }
      }
    }
  })
</script>
</html>

解释:
JS 第 8-14 行,我们定义了局部指令 v-focus,定义 inserted ,在节点被插入时获得焦点。
HTML 第 4 行,我们在 input 元素上使用指令,当打开时 id 为 name 的输入框会焦点。

上面我们介绍了 Vue.directive 第二个参数接收的是对象,这些都是可选的。接下来我们详细介绍这几个的作用:

指令会被传入以下参数:

指令的参数可以是动态的。例如,在 v-mydirective:[argument]=“value” 中,argument 参数可以根据组件实例数据进行更新!这使得指令可以在应用中被灵活使用。

例如你想要创建指令,用来改变元素的字体颜色。我们可以像这样创建通过指令值来更新字体颜色的指令:

<!DOCTYPE html>
<html lang="en">
<head>
  < charset="UTF-8">
  < name="viewport" content="width=device-width, initial-scale=1.0">
  < http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div v-color="color">Hello !</div>
    <button @click="changeColor">切换颜色</button>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
  Vue.directive('color', {
    bind: function (el, binding, vnode) {
      el.style.color = binding.value
    },
    update(el, binding) {
      el.style.color = binding.value
    }
  })
  var vm = new Vue({
    el: '#app',
    data() {
    	return {
        color: 'red'
      }
    },
    methods: {
      changeColor() {
        this.color = '#' + Math.floor( Math.random() *  ).toString();
      }
    }
  })
</script>
</html>

解释:
JS 第 3-10 行,我们定义了全局指令 v-color,定义 bind 设置元素的字体颜色,定义 update ,在节点更新时元素的字体颜色。
HTML 第 2 行,我们使用 v-color 指令,并动态传入值 color。
HTML 第 3 行,点击按钮切换 color 的值。
最终,当我们点击按钮时,“Hello !” 的字体颜色会变化。

上面的例子中我们通过指令动态设置了元素的字体颜色。但如果场景是我们需要元素的边框颜色又该怎么办呢?有些同学可能说我们可以再写 v-border-color 不就行了。那如果又有背景色的需求呢?这时使用动态参数就可以非常方便地根据每个组件实例来进行更新:

<!DOCTYPE html>
<html lang="en">
<head>
  < charset="UTF-8">
  < name="viewport" content="width=device-width, initial-scale=1.0">
  < http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div v-color:[colorstyle]="color" style="border: px solid #ccc;">Hello !</div>
    <div v-color:[borderstyle]="color" style="border: px solid #ccc;">Hello !</div>
    <div v-color:[backgroundstyle]="color" style="border: px solid #ccc;">Hello !</div>
    <button @click="changeColor">切换颜色</button>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
  Vue.directive('color', {
    bind: function (el, binding, vnode) {
      var s = binding.arg
      el.style[s] = binding.value
    },
    update(el, binding) {
      var s = binding.arg
      el.style[s] = binding.value
    }
  })
  var vm = new Vue({
    el: '#app',
    data() {
    	return {
        color: 'red',
        colorstyle: 'color',
        borderstyle: 'border-color',
        backgroundstyle: 'background-color',
      }
    },
    methods: {
      changeColor() {
        this.color = '#' + Math.floor( Math.random() *  ).toString();
      }
    }
  })
</script>
</html>

解释:
JS 第 3-12 行,我们定义了全局指令 v-color,定义 bind 和 update 。
HTML 第 2-4 行,我们使用 v-color 指令,并动态传入值 color。
HTML 第 5 行,点击按钮切换 color 的值。
最终,当我们点击 "切换颜色" 按钮时,分别会元素的 color、border-color、background-color 样式。

如果指令需要多个值,可以传入 JavaScript 对象字面量。记住,指令能够接受所有合法的 JavaScript 表达式:

<!DOCTYPE html>
<html lang="en">
<head>
  < charset="UTF-8">
  < name="viewport" content="width=device-width, initial-scale=1.0">
  < http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div v-font="font">Hello !</div>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
  Vue.directive('font', {
    bind: function (el, binding, vnode) {
      el.style.color = binding.value.color
      el.style['font-size'] = binding.value.size
    }
  })
  var vm = new Vue({
    el: '#app',
    data() {
    	return {
        font: {
          size: '26px',
          color: 'red'
        }
      }
    }
  })
</script>
</html>

解释:
JS 第 3-8 行,我们定义了全局指令 v-font。
JS 第 13-16 行,我们定义了对象类型的值 font。
HTML 第 2 行,我们使用 v-font 指令,并动态传入对象类型的值 font。

本节,我们带大家学习了指令在项目中的运用。主要知识点有以下几点:


联系我
置顶