Vue2极简教程005:修饰符完全指南

一、核心修饰符详解

1. 事件修饰符(v-on)

<!-- 阻止默认行为 -->
<form @submit.prevent="onSubmit"></form>

<!-- 阻止事件冒泡 -->
<div @click.stop="doThis"></div>

<!-- 事件只触发一次 -->
<button @click.once="doOnce"></button>

<!-- 按键修饰符 -->
<input @keyup.enter="submit" @keyup.13="submit">

<!-- 组合修饰符 -->
<div @click.stop.prevent="doThis"></div>

完整事件修饰符表

修饰符等效代码说明
.stopevent.stopPropagation()阻止冒泡
.preventevent.preventDefault()阻止默认行为
.capture-使用捕获模式
.selfif(event.target !== event.currentTarget) return仅元素自身触发
.once-只触发一次
.passive-不阻止默认行为(提升滚动性能)

2. 表单修饰符(v-model)

<!-- 输入时实时更新 -->
<input v-model="msg">

<!-- 失去焦点后更新 -->
<input v-model.lazy="msg">

<!-- 自动转为数字 -->
<input v-model.number="age" type="number">

<!-- 去除首尾空格 -->
<input v-model.trim="username">

3. 条件渲染修饰符

<!-- v-if 连续判断 -->
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else>C</div>

<!-- v-show 性能优化 -->
<div v-show="isVisible" style="display: none;">...</div>

二、特殊场景修饰符

1. 遍历修饰符(v-for)

<!-- 获取索引 -->
<li v-for="(item, index) in items"></li>

<!-- 遍历对象 -->
<li v-for="(value, key) in object"></li>

<!-- 使用key提升性能 -->
<div v-for="item in items" :key="item.id"></div>

2. 属性绑定修饰符(v-bind)

<!-- 动态class -->
<div :class="{ active: isActive }"></div>

<!-- 动态style -->
<div :style="{ color: activeColor }"></div>

<!-- prop绑定修饰符 -->
<child :title.sync="parentTitle"></child>
<!-- 等价于 -->
<child :title="parentTitle" @update:title="val => parentTitle = val"></child>

三、自定义修饰符开发

1. 全局自定义修饰符

// 注册v-model修饰符
Vue.config.keyCodes = {
  f1: 112,
  up: [38, 87]
}

// 自定义指令修饰符
Vue.directive('my-dir', {
  bind(el, binding) {
    if (binding.modifiers.uppercase) {
      el.value = el.value.toUpperCase()
    }
  }
})

2. 组件修饰符

Vue.component('my-input', {
  props: {
    value: String,
    modifiers: {
      type: Object,
      default: () => ({})
    }
  },
  methods: {
    emitValue(val) {
      if (this.modifiers.uppercase) {
        val = val.toUpperCase()
      }
      this.$emit('input', val)
    }
  },
  template: `
    <input 
      :value="value"
      @input="emitValue($event.target.value)"
    >
  `
})

四、修饰符组合技

1. 事件+按键组合

<input @keyup.alt.enter="clear">

<!-- 精确控制系统 -->
<input @keyup.ctrl.exact="onCtrlClick">

2. v-model + 自定义修饰符

// 自定义capitalize修饰符
Vue.directive('model', {
  update(el, binding, vnode) {
    if (binding.modifiers.capitalize) {
      el.value = el.value.charAt(0).toUpperCase() + el.value.slice(1)
      vnode.context[binding.expression] = el.value
    }
  }
})

五、性能优化修饰符

1. v-once 静态内容缓存

<div v-once>{{ staticContent }}</div>

2. .prevent 与 .passive 的抉择

<!-- 需要阻止默认行为时 -->
<div @touchmove.prevent></div>

<!-- 只需要监听滚动时(提升性能) -->
<div @scroll.passive="onScroll"></div>

六、修饰符原理剖析

  1. 编译阶段处理

    // 模板编译结果示例
    _c('div', {
      on: {
        "click": function($event) {
          $event.stopPropagation()
          doThis($event)
        }
      }
    })
  2. 修饰符优先级

    • 事件修饰符从右到左处理
    • v-on:click.prevent.self 会先阻止默认行为再判断self
    • v-on:click.self.prevent 会先判断self再阻止默认行为
  3. 自定义修饰符实现

    function genModifiersCode(modifiers) {
      let code = ''
      for (const key in modifiers) {
        code += `if(modifiers.${key}){/* 处理逻辑 */}`
      }
      return code
    }

七、实战案例

1. 自动聚焦指令

Vue.directive('focus', {
  inserted(el, binding) {
    if (binding.modifiers.delay) {
      setTimeout(() => el.focus(), 300)
    } else {
      el.focus()
    }
  }
})

// 使用
<input v-focus.delay>

2. 金额输入控制

<input 
  v-model.number="amount"
  @keypress.only-number
>

Vue.directive('only-number', {
  bind(el) {
    el.handler = function() {
      el.value = el.value.replace(/[^\d.]/g, '')
    }
    el.addEventListener('input', el.handler)
  }
})

最佳实践建议

  1. 频繁触发的事件(如scroll)使用.passive
  2. 表单验证使用.lazy减少触发频率
  3. 列表渲染务必使用:key
  4. 避免过度使用.sync修饰符(Vue3已重构此功能)

通过合理使用修饰符,可以:

  • 减少模板中的JavaScript代码
  • 提升代码可读性
  • 实现声明式的DOM操作
  • 优化应用性能

添加新评论