Vue3内置属性

Vue 3 内置属性完全指南

本文档从零开始讲解 Vue 3 的内置属性:组件实例上由 Vue 提供的 $data$props$el$refs$parent$root$attrs$slots$emit$nextTick 等,以及模板里的特殊属性 keyrefis,配有大量示例,适合新手系统学习。


一、什么是“内置属性”?

1.1 两类“内置”东西

在 Vue 里,“内置”大致分两类:

  1. 组件实例上的内置属性:每个组件实例上都有一些以 $ 开头的属性或方法,如 $data$refs$nextTick,由 Vue 自动挂上去,用来访问数据、DOM、父/根实例等。
  2. 模板里的特殊属性:如 keyrefis,在模板里写时有特殊含义,不是普通 HTML 属性。

本文先讲实例上的内置属性,再讲模板里的特殊属性
里没有 this,部分内置能力通过 defineExposeuseAttrsuseSlotsgetCurrentInstance 等使用,文中会一并说明。


二、$data:组件的数据对象

2.1 是什么?

$data 指向组件 data 选项返回的响应式对象
在选项式 API 里,this.$data 和直接写 this.xxx(data 里的属性)是同一份数据。

2.2 使用场景

一般直接用 this.xxx 即可,很少直接写 this.$data
需要“遍历所有 data 字段”或“把整个 data 序列化”时可以用 this.$data

export default {
  data() {
    return { count: 0, name: '' }
  },
  mounted() {
    console.log(this.$data)
    console.log(this.$data === this) // false,$data 是 data 返回的对象
    console.log(this.$data.count === this.count)
  }
}

2.3 在 里

没有 this,没有 $data;数据就是你定义的 refreactive,直接访问即可。


三、$props:当前组件接收的 props

3.1 是什么?

$props 是父组件传入的 props 组成的对象,和 definePropsprops 选项对应,是只读、响应式的。

3.2 使用场景

在选项式 API 里需要“把整个 props 传给子组件”或“遍历 props”时可用 this.$props

export default {
  props: ['title', 'count'],
  mounted() {
    console.log(this.$props)
  }
}

里用 defineProps() 的返回值,没有 $props 这个名字,但含义相同。


四、$el:根 DOM 元素

4.1 是什么?

$el 是组件根 DOM 元素
只有组件挂载完成后才有(在 mounted 及之后可用);若组件有多个根节点(Vue 3 Fragment),$el 指向第一个根节点。
里没有 this,要用 $el 需通过 ref 绑定根元素,或 getCurrentInstance()?.proxy?.$el(不推荐依赖,建议用 ref)。

4.2 使用场景

需要拿到“整个组件根节点”时(如交给第三方库、测量尺寸),在选项式里可用 this.$el

export default {
  mounted() {
    console.log(this.$el)
    this.$el.style.border = '1px solid red'
  }
}

五、$refs:模板 ref 的集合

5.1 是什么?

在模板里写的 ref=”xxx”,会在 this.$refs.xxx 上暴露出来:

  • 绑在 DOM 上,$refs.xxx 是该 DOM 元素;
  • 绑在子组件上,$refs.xxx 是该子组件的实例(或子组件通过 defineExpose 暴露的内容)。

5.2 使用场景

需要直接操作子 DOM调用子组件方法时用 $refs
$refsmounted 之后才有,且 v-if 控制的 ref 可能在未渲染时为 undefined

<template>
  <input ref="inputRef" />
  <Child ref="childRef" />
</template>

<script>
export default {
  mounted() {
    this.$refs.inputRef?.focus()
    this.$refs.childRef?.someMethod()
  }
}
</script>

里不用 $refs,而是自己 const inputRef = ref(null),模板里 ref=”inputRef”,用 inputRef.value 访问。


六、$parent 与 $root

6.1 $parent

$parent父组件实例(若存在)。
通过 this.$parent 可以访问父组件的 data、methods 等,但不推荐用这种方式通信,优先用 props + emitprovide/inject

mounted() {
  console.log(this.$parent)
}

6.2 $root

$root当前组件树的根实例(即 createApp(App) 挂载的那个根)。
可用于“跨多层”访问根上的数据或方法,但更推荐 provide/injectPinia

mounted() {
  console.log(this.$root)
}

里没有 this,可用 getCurrentInstance()?.parentgetCurrentInstance()?.root,同样不推荐依赖,仅作了解。


七、$attrs:未声明为 props 的属性

7.1 是什么?

父组件在子组件上绑了没有在子组件 props(或 emits)里声明的属性/事件,会落在 $attrs 里。
例如父写了 :id=”xxx”class=”box”,子没有声明 id,那 $attrs 里就有 idclass 等。
常用于属性透传:在子组件根节点上写 v-bind=”$attrs”,把这些属性继续往下传。

7.2 使用场景

<!-- 父 -->
<MyInput id="my-id" class="input" placeholder="请输入" />

<!-- 子:不声明 id、class,它们会进 $attrs -->
<template>
  <input v-bind="$attrs" />
</template>

<script>
export default {
  inheritAttrs: false
}
</script>

里用 useAttrs() 拿到和 $attrs 等价的对象。

import { useAttrs } from 'vue'
const attrs = useAttrs()

八、$slots:插槽内容

8.1 是什么?

$slots 是一个对象,键是插槽名(default 表示默认插槽),值是对应的插槽内容(VNode 或函数)。
用来判断“有没有传入某插槽”或“在 JS 里渲染插槽”。

8.2 使用场景

export default {
  mounted() {
    console.log(this.$slots.default)
    console.log(this.$slots.header)
  }
}

模板里一般用 即可;需要“根据是否有插槽再决定是否渲染某块”时,可判断 this.$slots.xxx
里用 useSlots()

import { useSlots } from 'vue'
const slots = useSlots()
if (slots.header) { ... }

九、$emit:触发自定义事件

9.1 是什么?

$emit 是组件用来向父组件触发自定义事件的方法:this.$emit(‘事件名’, 参数)
父组件用 @事件名 监听。

9.2 使用场景

export default {
  methods: {
    submit() {
      this.$emit('submit', { id: 1 })
    }
  }
}

里用 defineEmits() 返回的 emit 函数,不用 this.$emit


十、$nextTick:DOM 更新后执行

10.1 是什么?

$nextTick 接收一个回调(或返回 Promise),在 Vue 把数据变化应用到 DOM 之后再执行。
用于“改完数据后立刻操作 DOM”的场景,如滚动到底部、focus 到新出现的输入框。

10.2 使用场景

this.list.push(newItem)
this.$nextTick(() => {
  this.$refs.list.scrollTop = this.$refs.list.scrollHeight
})

里从 vue 引入 nextTick,直接 await nextTick()nextTick(fn),不用 this.$nextTick

import { nextTick } from 'vue'
await nextTick()

十一、$options:组件配置

11.1 是什么?

$options 是组件在定义时传入的配置对象(即 export default { … }defineComponent 的那一坨),包含 namedatamethods 等。
也可在这里挂自定义属性,如 this.$options.myOption

11.2 使用场景

export default {
  name: 'MyComp',
  myOption: 'hello',
  mounted() {
    console.log(this.$options.name)
    console.log(this.$options.myOption)
  }
}

一般用于取 name、自定义选项或高阶场景,新手较少直接用。


十二、getCurrentInstance(在 setup 里拿“实例”)

12.1 是什么?

setup() 里没有 this,若需要访问当前组件实例(例如拿 $el$parent),可以用 getCurrentInstance()
返回的 instance 上有 proxy(约等于 this)、parentroot 等,多用于库或高级用法。

12.2 使用场景

import { getCurrentInstance } from 'vue'

const instance = getCurrentInstance()
console.log(instance?.proxy?.$el)
console.log(instance?.parent)

注意getCurrentInstance 只在 setup 或 同步生命周期 里有效,且官方不推荐在业务里强依赖内部实例,优先用 refprovide/injectprops/emit


十三、模板里的特殊属性:key

13.1 是什么?

key 是 Vue 在列表渲染条件切换时用来唯一标识节点的特殊属性。
v-for 里必须给每项一个稳定、唯一key,便于 Vue 正确复用或更新 DOM;在 或组件上写 key 可强制“不同 key 当不同实例”重新创建。

13.2 使用场景

<li v-for="item in list" :key="item.id">{{ item.name }}</li>
<component :is="current" :key="current" />

key 改变时,Vue 会先销毁旧节点再创建新节点,可用于“切换 tab 时重置组件状态”。


十四、模板里的特殊属性:ref

14.1 是什么?

ref 在模板里用于把 DOM 或子组件实例绑定到 script 里的一个 ref 变量
在选项式里绑定到 this.$refs.xxx;在 里绑定到你声明的 ref(null)

14.2 使用场景

<input ref="inputRef" />
const inputRef = ref(null)
onMounted(() => {
  inputRef.value?.focus()
})

详见《Vue3组件.md》中“模板 ref”一节。


十五、模板里的特殊属性:is

15.1 是什么?

is 用于动态组件:is=”组件名或组件对象” 决定当前渲染哪个组件。
常与 配合。

15.2 使用场景

<component :is="currentTabComponent" />
const currentTabComponent = ref('TabHome')

:is 用在原生 HTML 标签上,用于解析为 Vue 组件(如

里用 ),新手较少用到。


十六、内置属性 / 特殊属性速查表

名称 类型 含义 在 中
$data 实例属性 data 返回的对象 无 this,直接用 ref/reactive
$props 实例属性 当前 props 对象 defineProps() 的返回值
$el 实例属性 根 DOM 元素 用 ref 绑根元素或 getCurrentInstance
$refs 实例属性 模板 ref 集合 自己 ref(null) + 模板 ref=”变量”
$parent 实例属性 父组件实例 getCurrentInstance()?.parent
$root 实例属性 根实例 getCurrentInstance()?.root
$attrs 实例属性 未声明的属性/事件 useAttrs()
$slots 实例属性 插槽内容 useSlots()
$emit 实例方法 触发自定义事件 defineEmits() 返回的 emit
$nextTick 实例方法 DOM 更新后执行回调 import { nextTick } from ‘vue’
$options 实例属性 组件配置对象 一般不直接用
key 模板属性 节点唯一标识 同左
ref 模板属性 绑定 DOM/组件到 ref 同左
is 模板属性 动态组件 同左

十七、学习建议

  1. 先掌握模板里的 key、ref、is(key 在 v-for 必写,ref 拿 DOM/子组件,is 做动态组件)。
  2. 在选项式里用到 this 时,知道 $refs$emit$nextTick$attrs 的用途即可。
  3. 时,用 definePropsdefineEmitsuseAttrsuseSlotsnextTickref 替代对应的 $ 属性。
  4. $parent$rootgetCurrentInstance 仅作了解,业务里优先 props/emitprovide/injectPinia

把本文档里的 $refs$emit$nextTickkeyref 在项目里用一遍,会掌握得更牢。祝你学习顺利。

发表评论