Vue 核心特性详解:计算属性、监听属性与事件交互实战指南

文章目录


文章目录


前言

在 Vue 组件化开发中,"数据高效处理" 与 "组件灵活交互" 是构建稳定可维护应用的核心,而计算属性、监听属性、事件处理器及自定义事件正是解决这些问题的关键特性;但不少开发者初学时易混淆其适用场景、对细节理解不深,进而导致代码问题,因此本文通过 "概念解析 + 代码示例 + 场景对比" 拆解四大特性的逻辑、用法与注意事项,助力读者明确适用场景、掌握对应开发思路,为复杂 Vue 应用开发筑牢基础


一、Vue的计算属性?

Vue的计算属性

  1. vue的介绍:
    Vue 的计算属性(computed)是用于声明式地处理复杂数据计算的属性,依赖于其他响应式数据,当依赖的数据变化时,计算属性会自动重新计算并缓存结果。
  2. 核心特点
  • 依赖追踪:计算属性会依赖于 data 或其他计算属性中的数据,当依赖项变化时,计算属性会自动重新计算。
  • 缓存机制:只有当依赖项发生变化时,才会重新计算;如果依赖项不变,多次访问计算属性会直接返回缓存的结果,避免重复计算(提升性能)。
  • 声明式:用类似属性的方式定义,使用时像普通数据一样直接访问,无需加括号。
  1. 基本用法
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
  1. 监听属性:
    Vue 的监听属性(watch) 用于监视响应式数据的变化,当被监视的数据发生改变时,会自动执行指定的回调函数,常用于实现复杂的业务逻辑(如数据变化后的异步操作、多数据联动等)。
  2. 核心作用
    监听指定数据的变化,触发自定义逻辑(比如数据变化后发送请求、更新其他数据、执行动画等)。
  3. 基本用法
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)
  1. 如果监视的是对象或数组,默认情况下 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)
  1. 默认情况下,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 原生事件。

  1. 直接执行简单逻辑
dart 复制代码
<template>
  <!-- 点击按钮,直接修改数据(适合简单逻辑) -->
  <button @click="count += 1">点击+1</button>
  <p>计数:{{ count }}</p>
</template>

<script>
export default {
  data() {
    return { count: 0 };
  }
};
</script>
  1. 调用方法(适合复杂逻辑)
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>
  1. 传递自定义参数
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 种绑定方式
  1. 模板直接绑定(最常用)
    核心逻辑:父组件在子组件标签上用@事件名绑定处理方法,子组件通过$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>

适用场景:事件逻辑固定,无需动态控制绑定 / 解绑。

  1. 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>

适用场景:需延迟绑定(如点击按钮后才开启监听)。

  1. 动态绑定 + 解绑(临时事件)

核心逻辑:用 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 应用

相关推荐
1024小神4 小时前
uniapp+vue3+vite+ts+xr-frame实现ar+vr渲染踩坑记
前端
测试界清流4 小时前
基于pytest的接口测试
前端·servlet
知识分享小能手4 小时前
微信小程序入门学习教程,从入门到精通,自定义组件与第三方 UI 组件库(以 Vant Weapp 为例) (16)
前端·学习·ui·微信小程序·小程序·vue·编程
trsoliu4 小时前
多仓库 Workspace 协作机制完整方案
前端
啦工作呢5 小时前
数据可视化 ECharts
前端·信息可视化·echarts
NoneSL5 小时前
Uniapp UTS插件开发实战:引入第三方SDK
前端·uni-app
trsoliu5 小时前
Claude Code Templates
前端·人工智能
wangpq5 小时前
使用rerender-spa-plugin在构建时预渲染静态HTML文件优化SEO
前端·javascript·vue.js
KongHen5 小时前
完美解决请求跨域问题
前端