Vue 3 内置属性

Vue 3 提供了一些 内置属性,用于在组件内部访问特定信息,如组件实例、插槽、生命周期钩子等。以下是 Vue 3 常见的 内置属性 及其用法。


1. $attrs

$attrs 用于接收 未被 props 绑定 的属性,适用于组件透传(如 v-bind="$attrs")。

示例

<template>
  <ChildComponent class="custom-class" data-id="123" custom-prop="hello" />
</template>

<script setup>
import ChildComponent from './ChildComponent.vue';
</script>

子组件 ChildComponent.vue

<template>
  <div v-bind="$attrs">我是子组件</div>
</template>

<script setup>
import { useAttrs } from 'vue';

const attrs = useAttrs();
console.log(attrs); // { class: "custom-class", data-id: "123", custom-prop: "hello" }
</script>

说明

  • $attrs 包含所有未声明为 props 的属性,如 classdata-idcustom-prop
  • v-bind="$attrs" 让这些属性传递到根元素,避免手动绑定。

2. $slots

$slots 用于访问插槽内容,通常在 子组件 中使用。

示例

父组件

<ParentComponent>
  <template #default>默认插槽内容</template>
  <template #header>我是标题</template>
</ParentComponent>

子组件 ParentComponent.vue

<template>
  <header v-if="$slots.header">
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
</template>

说明

  • $slots.header 检测 header 插槽是否存在。
  • <slot name="header"></slot> 用于渲染具名插槽。
  • <slot></slot> 用于渲染默认插槽。

3. $el

$el 获取 组件的根 DOM 元素

示例

<template>
  <button>点击我</button>
</template>

<script>
export default {
  mounted() {
    console.log(this.$el); // 获取组件的根元素 <button>
  }
};
</script>

说明

  • $el 只在 选项式 API 中可用,在 setup() 需使用 ref() 获取 DOM。

4. $refs

$refs 获取 DOM 元素或子组件实例

示例

<template>
  <input ref="inputRef" type="text" placeholder="输入内容">
  <button @click="focusInput">聚焦</button>
</template>

<script setup>
import { ref, onMounted } from 'vue';

const inputRef = ref(null);

const focusInput = () => {
  inputRef.value.focus(); // 让 input 聚焦
};

onMounted(() => {
  console.log(inputRef.value); // 获取 <input> 元素
});
</script>

说明

  • ref="inputRef" 绑定到元素。
  • inputRef.value 获取元素实例,可用于 focus()value 等操作。

获取子组件

<ChildComponent ref="childRef" />

export default {
  mounted() {
    console.log(this.$refs.childRef); // 获取子组件实例
  }
};


5. $emit

$emit 用于 触发事件,实现 父子组件通信

示例

子组件

<template>
  <button @click="sendMessage">点击发送</button>
</template>

<script setup>
import { defineEmits } from 'vue';

const emit = defineEmits(['customEvent']);

const sendMessage = () => {
  emit('customEvent', '来自子组件的消息');
};
</script>

父组件

<template>
  <ChildComponent @customEvent="handleMessage" />
</template>

<script setup>
const handleMessage = (msg) => {
  console.log("收到子组件消息:", msg);
};
</script>

说明

  • emit('customEvent', '数据') 触发事件,父组件监听 @customEvent

6. $parent & $root

$parent$root 用于访问 父组件根组件,但 Vue 3 推荐使用 provide/inject 代替。

示例

<template>
  <ChildComponent />
</template>

<script>
export default {
  mounted() {
    console.log(this.$root); // 访问根组件实例
  }
};
</script>

export default {
  mounted() {
    console.log(this.$parent); // 访问父组件实例
  }
};

Vue 3 建议

  • 代替 $parent 使用 provide/inject
  • 代替 $root 使用 全局状态管理 (Vuex/Pinia)

7. $options

$options 获取组件的 选项对象

示例

export default {
  name: 'MyComponent',
  data() {
    return { msg: 'Hello' };
  },
  mounted() {
    console.log(this.$options.name); // MyComponent
  }
};

说明

  • $options 适用于 选项式 APIsetup() 中可以使用 defineOptions()

8. $watch

$watch 监听数据变化(选项式 API)。

示例

export default {
  data() {
    return { count: 0 };
  },
  watch: {
    count(newVal, oldVal) {
      console.log(`count 从 ${oldVal} 变为 ${newVal}`);
    }
  }
};

Vue 3 推荐

  • 组合式 API 中使用 watch() 替代 $watch

9. defineExpose()

Vue 3 defineExpose() 用于在 setup() 中暴露方法/数据。

示例

子组件

<template>
  <button @click="increment">增加</button>
</template>

<script setup>
import { ref, defineExpose } from 'vue';

const count = ref(0);

const increment = () => {
  count.value++;
  console.log('当前 count:', count.value);
};

// 暴露 `count` 和 `increment`
defineExpose({ count, increment });
</script>

父组件

<template>
  <ChildComponent ref="childRef" />
  <button @click="callChildMethod">获取子组件数据</button>
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const childRef = ref(null);

const callChildMethod = () => {
  console.log(childRef.value.count); // 访问子组件的 `count`
  childRef.value.increment(); // 调用子组件的方法
};
</script>

说明

  • defineExpose()setup() 内的数据可被 ref 访问。

总结

内置属性作用
$attrs传递未声明的 props
$slots访问插槽
$el获取根 DOM
$refs获取 DOM 或子组件
$emit触发事件
$parent访问父组件(不推荐)
$root访问根组件(不推荐)
$options获取组件选项
$watch监听数据(推荐 watch()
defineExpose()暴露 setup() 内数据

Vue 3 更推荐 组合式 API (setup()watch()provide/inject) 来代替某些 $ 内置属性,使代码更清晰、可维护性更高 🚀。