文章目录
文章目录
- 文章目录
 - 前言
 - 一、Vue的计算属性?
 - 二、vue的监听属性
 - 
- 
- 
- 
- 一、watch
 - [二、深度监听(deep: true)](#二、深度监听(deep: true))
 - [三、立即执行(immediate: true)](#三、立即执行(immediate: true))
 
 
 - 
 - 计算属性(computed)与监听属性(watch)的区别
 
 - 
 
 - 
 - 三、事件处理器
 - 
- 
- 
- 
- 
- [一、基础用法(绑定 DOM 事件)](#一、基础用法(绑定 DOM 事件))
 - [二、事件修饰符(简化 DOM 操作)](#二、事件修饰符(简化 DOM 操作))
 
 
 - 
 
 - 
 - [Vue 事件修饰符对照表](#Vue 事件修饰符对照表)
 - 常见组合用法
 
 - 
 
 - 
 - 四、自定义事件
 - 
- 
- 
- 
- [一、自定义事件(子传父):3 种绑定方式](#一、自定义事件(子传父):3 种绑定方式)
 - [二、props 传递函数(父传子函数,子调用)](#二、props 传递函数(父传子函数,子调用))
 
 
 - 
 - 通信方式对比
 
 - 
 
 - 
 - 总结
 
前言
在 Vue 组件化开发中,"数据高效处理" 与 "组件灵活交互" 是构建稳定可维护应用的核心,而计算属性、监听属性、事件处理器及自定义事件正是解决这些问题的关键特性;但不少开发者初学时易混淆其适用场景、对细节理解不深,进而导致代码问题,因此本文通过 "概念解析 + 代码示例 + 场景对比" 拆解四大特性的逻辑、用法与注意事项,助力读者明确适用场景、掌握对应开发思路,为复杂 Vue 应用开发筑牢基础
一、Vue的计算属性?
Vue的计算属性
- vue的介绍:
Vue 的计算属性(computed)是用于声明式地处理复杂数据计算的属性,依赖于其他响应式数据,当依赖的数据变化时,计算属性会自动重新计算并缓存结果。 - 核心特点
 
- 依赖追踪:计算属性会依赖于 data 或其他计算属性中的数据,当依赖项变化时,计算属性会自动重新计算。
 - 缓存机制:只有当依赖项发生变化时,才会重新计算;如果依赖项不变,多次访问计算属性会直接返回缓存的结果,避免重复计算(提升性能)。
 - 声明式:用类似属性的方式定义,使用时像普通数据一样直接访问,无需加括号。
 
- 基本用法
 
            
            
              dart
              
              
            
          
          vue
<template>
  <div>
    <p>原始数据:{{ message }}</p>
    <p>计算后的数据:{{ reversedMessage }}</p> <!-- 直接访问计算属性 -->
  </div>
</template>
<script>
export default {
  data() {
    return {
      message: 'Hello Vue'
    };
  },
  computed: {
    // 计算属性:反转 message 的字符串
    reversedMessage() {
      // 依赖于 data 中的 message
      return this.message.split('').reverse().join('');
    }
  }
};
</script>
        - 当 message 变化时(比如通过其他操作修改 this.message = 'Hi'),reversedMessage 会自动重新计算并更新视图。
 - 多次访问 this.reversedMessage 时,只要 message 没变,就会直接返回缓存值,不会重复执行 split/reverse/join。
 
与方法(methods)的区别
| 计算属性(computed) | 方法(methods) | 
|---|---|
| 有缓存,依赖项不变则不重新计算 | 无缓存,每次调用都会重新执行 | 
| 使用时直接访问({{ prop }}) | 使用时需要调用({{ fn() }}) | 
二、vue的监听属性
一、watch
- 监听属性:
Vue 的监听属性(watch) 用于监视响应式数据的变化,当被监视的数据发生改变时,会自动执行指定的回调函数,常用于实现复杂的业务逻辑(如数据变化后的异步操作、多数据联动等)。 - 核心作用
监听指定数据的变化,触发自定义逻辑(比如数据变化后发送请求、更新其他数据、执行动画等)。 - 基本用法
 
            
            
              dart
              
              
            
          
          <template>
  <div>
    <input v-model="message" placeholder="输入内容">
    <p>监听结果:{{ watchResult }}</p>
  </div>
</template>
<script>
export default {
  data() {
    return {
      message: '',
      watchResult: ''
    };
  },
  // 监听属性配置
  watch: {
    // 监视 data 中的 message 属性
    message(newVal, oldVal) {
      // 当 message 变化时,自动执行此函数
      // newVal:变化后的值;oldVal:变化前的值
      this.watchResult = `内容从 "${oldVal}" 变成了 "${newVal}"`;
    }
  }
};
</script>
        - 当输入框中 message 的值变化时,watch 中的 message 回调会自动执行,更新 watchResult 的内容。
 
二、深度监听(deep: true)
- 如果监视的是对象或数组,默认情况下 watch 只会监听对象的 "引用变化"(如重新赋值),不会监听对象内部属性的变化。此时需要用 deep: true 开启深度监听。
 
            
            
              dart
              
              
            
          
          <script>
export default {
  data() {
    return {
      user: {
        name: '张三',
        age: 20
      }
    };
  },
  watch: {
    // 监听对象 user 的内部属性变化
    user: {
      handler(newVal, oldVal) {
        console.log('user 内部属性变化了', newVal);
      },
      deep: true // 开启深度监听(监听对象内部所有属性)
    },
    // 也可以直接监听对象的某个具体属性(更高效)
    'user.age'(newVal) {
      console.log('年龄变化为:', newVal);
    }
  }
};
</script>
        当 this.user.age = 21 时,两个监听都会触发(推荐直接监听具体属性,性能更好)。
三、立即执行(immediate: true)
- 默认情况下,watch 回调在数据第一次变化时才执行。如果需要初始加载时就执行一次,可以用 immediate: true。
 
            
            
              dart
              
              
            
          
          vue
<script>
export default {
  data() {
    return {
      searchKey: '初始值'
    };
  },
  watch: {
    searchKey: {
      handler(newVal) {
        console.log('执行搜索:', newVal); // 初始时就会执行一次
      },
      immediate: true // 立即执行(组件加载时触发)
    }
  }
};
</script>
        计算属性(computed)与监听属性(watch)的区别
| 特性 | 监听属性(watch) | 计算属性(computed) | 
|---|---|---|
| 主要用途 | 监听数据变化并执行副作用(如异步请求、日志打印) | 根据依赖计算衍生值(同步操作) | 
| 缓存机制 | 无缓存,数据变化就会触发 | 有缓存,依赖不变则不重新计算 | 
| 适用场景 | 适合处理复杂逻辑(如多数据联动、异步操作) | 适合简单的衍生值计算(如拼接、过滤) | 
三、事件处理器
Vue 的事件处理器是用于监听 DOM 事件或自定义事件,并触发对应逻辑的机制,核心是通过 v-on 指令(或简写 @)绑定事件,实现 "用户操作 → 代码执行" 的交互。
一、基础用法(绑定 DOM 事件)
通过 v-on:事件名="处理函数" 或简写 @事件名="处理函数",绑定点击、输入、鼠标移动等 DOM 原生事件。
- 直接执行简单逻辑
 
            
            
              dart
              
              
            
          
          <template>
  <!-- 点击按钮,直接修改数据(适合简单逻辑) -->
  <button @click="count += 1">点击+1</button>
  <p>计数:{{ count }}</p>
</template>
<script>
export default {
  data() {
    return { count: 0 };
  }
};
</script>
        - 调用方法(适合复杂逻辑)
 
            
            
              dart
              
              
            
          
          <template>
  <!-- 点击按钮,调用 handleClick 方法 -->
  <button @click="handleClick">点击触发方法</button>
  <input @input="handleInput" placeholder="输入内容">
</template>
<script>
export default {
  methods: {
    // 处理点击事件
    handleClick() {
      alert('按钮被点击了');
    },
    // 处理输入事件(可接收事件对象 event)
    handleInput(event) {
      console.log('输入的内容:', event.target.value);
    }
  }
};
</script>
        - 传递自定义参数
 
            
            
              dart
              
              
            
          
          如果需要给事件方法传参,同时保留原生 event 对象,可通过 $event 显式传递。
vue
<template>
  <!-- 传递自定义参数 + 原生 event 对象 -->
  <button @click="handleBtnClick('参数1', $event)">点击传参</button>
</template>
<script>
export default {
  methods: {
    handleBtnClick(param, event) {
      console.log('自定义参数:', param); // 输出 "参数1"
      console.log('事件目标:', event.target); // 输出按钮 DOM 元素
    }
  }
};
</script>
        二、事件修饰符(简化 DOM 操作)
Vue 提供事件修饰符,用于快速处理常见的 DOM 事件细节(如阻止默认行为、阻止冒泡),避免在方法中写 event.preventDefault() 这类重复代码。
常用修饰符:
Vue 事件修饰符对照表
| 修饰符 | 作用 | 示例 | 
|---|---|---|
.prevent | 
阻止默认事件行为(如表单提交、链接跳转) | @submit.prevent | 
.stop | 
阻止事件冒泡(防止父元素触发相同事件) | @click.stop | 
.once | 
事件只触发一次 | @click.once | 
.self | 
仅当事件目标为元素自身时触发(忽略子元素触发的事件) | @click.self | 
.enter | 
限定键盘事件仅在按下回车键时触发(其他按键无效) | @keyup.enter | 
.stop.prevent | 
组合修饰符:同时阻止冒泡和默认行为(顺序可调换) | @click.stop.prevent | 
.capture | 
使用事件捕获模式(从外到内触发) | @click.capture | 
.passive | 
提升滚动性能(不与.prevent共用) | 
@scroll.passive | 
常见组合用法
- 表单提交拦截 :
@submit.prevent - 阻止冒泡的点击事件 :
@click.stop - 一次性事件监听 :
@click.once - 按键过滤 :
@keyup.enter(回车键)、@keyup.esc(ESC键) 
注意:修饰符可串联使用(如
@click.stop.prevent),但顺序可能影响结果。
四、自定义事件
一、自定义事件(子传父):3 种绑定方式
- 模板直接绑定(最常用)
核心逻辑:父组件在子组件标签上用@事件名绑定处理方法,子组件通过$emit触发。示例:
● 父组件(Parent.vue):vue 
            
            
              dart
              
              
            
          
          <template>
  <Child @sendMsg="handleMsg" /> <!-- 绑定自定`在这里插入代码片`义事件sendMsg -->
</template>
<script>
export default {
  methods: {
    handleMsg(msg) { console.log("收到子组件消息:", msg); }
  }
};
</script>
        ● 子组件(Child.vue):vue
            
            
              dart
              
              
            
          
          <template>
  <button @click="triggerEvent">发送消息</button>
</template>
<script>
export default {
  methods: {
    triggerEvent() { this.$emit("sendMsg", "Hello 父组件"); } // 触发事件并传参
  }
};
</script>
        适用场景:事件逻辑固定,无需动态控制绑定 / 解绑。
- ref 手动绑定(动态绑定)
 
核心逻辑:父组件通过ref获取子组件实例,用$on手动绑定事件,可控制绑定时机。示例:
● 父组件(Parent.vue):vue
            
            
              dart
              
              
            
          
          <template>
  <Child ref="childRef" />
  <button @click="bindEvent">绑定事件</button>
</template>
<script>
export default {
  methods: {
    bindEvent() {
      // 手动绑定事件sendNum,点击子组件按钮后触发
      this.$refs.childRef.$on("sendNum", (num) => {
        console.log("收到数字:", num);
      });
    }
  }
};
</script>
        ● 子组件(Child.vue):vue
            
            
              dart
              
              
            
          
          <template>
  <button @click="triggerNum">发送随机数</button>
</template>
<script>
export default {
  methods: {
    triggerNum() { this.$emit("sendNum", Math.random()); }
  }
};
</script>
        适用场景:需延迟绑定(如点击按钮后才开启监听)。
- 动态绑定 + 解绑(临时事件)
 
核心逻辑:用 o n 绑定事件后,通过 on绑定事件后,通过 on绑定事件后,通过off手动解绑,避免内存泄漏。示例:
● 父组件(Parent.vue):vue
            
            
              dart
              
              
            
          
          <template>
  <Child ref="tempChild" />
  <button @click="bind">绑定临时事件</button>
  <button @click="unbind">解绑</button>
</template>
<script>
export default {
  methods: {
    bind() {
      this.$refs.tempChild.$on("tempEvent", this.handleTemp);
    },
    unbind() {
      this.$refs.tempChild.$off("tempEvent", this.handleTemp); // 精准解绑
    },
    handleTemp(data) { console.log("临时事件数据:", data); }
  }
};
</script>
        ● 子组件(Child.vue):vue
            
            
              dart
              
              
            
          
          <template>
  <button @click="triggerTemp">触发临时事件</button>
</template>
<script>
export default {
  methods: {
    triggerTemp() { this.$emit("tempEvent", "临时数据"); }
  }
};
</script>
        适用场景:弹窗等临时组件,需在关闭后解绑事件。
二、props 传递函数(父传子函数,子调用)
核心逻辑:父组件将函数通过 props 传给子组件,子组件直接调用该函数传递数据(本质是 "父传子" 的反向利用)。示例:
● 父组件(Parent.vue):vue
            
            
              dart
              
              
            
          
          <template>
  <Child :onReceive="handleReceive" /> <!-- 传递函数onReceive -->
</template>
<script>
export default {
  methods: {
    handleReceive(data) { console.log("通过props收到:", data); }
  }
};
</script>
        ● 子组件(Child.vue):vue
            
            
              dart
              
              
            
          
          <template>
  <button @click="callParent">调用父组件函数</button>
</template>
<script>
export default {
  props: { onReceive: Function }, // 接收父组件传递的函数
  methods: {
    callParent() { this.onReceive("通过props传递的数据"); } // 调用函数传参
  }
};
</script>
        适用场景:简单的子向父通信,逻辑较直接时使用。
通信方式对比
| 方式 | 核心逻辑 | 通信方向 | 适用场景 | 注意事项 | 
|---|---|---|---|---|
| 模板绑定自定义事件 | 子 $emit + 父 @事件名 | 
子→父 | 固定事件,无需动态控制 | 无需手动解绑(组件销毁自动失效) | 
| ref 手动绑定事件 | 父 $on绑定 + 子 $emit | 
子→父 | 需延迟绑定事件 | 确保 $refs 已获取子组件 | 
| 动态绑定 + 解绑 | $on绑定 + $off解绑 | 
子→父 | 临时事件,避免内存泄漏 | 解绑需匹配事件名和处理函数 | 
| props 传递函数 | 父传函数 + 子调用函数传参 | 子→父 | 简单通信,逻辑直接 | 避免过度使用(易混淆 props 用途) | 
总结
本文围绕 Vue 核心交互与数据处理能力,系统讲解了四大关键特性:计算属性,监听属性,事件处理器,自定义事件。四大特性各有侧重 ------ 计算属性聚焦 "数据衍生",监听属性聚焦 "数据变化后的逻辑",事件处理器聚焦 "用户交互触发",自定义事件聚焦 "组件通信",共同构成 Vue 组件化开发中数据处理与交互的核心能力体系,帮助开发者构建高效、可维护的 Vue 应用