阿里云主机折上折
  • 微信号
Current Site:Index > The new feature of template references (ref) translates this sentence into English.

The new feature of template references (ref) translates this sentence into English.

Author:Chuan Chen 阅读数:61062人阅读 分类: Vue.js

Template Refs (ref) New Features

Vue.js 3.x has significantly upgraded the template ref functionality, providing more flexible and powerful ways to use refs. These improvements allow developers to manipulate DOM elements and component instances more directly while maintaining Vue's reactivity.

Basic Usage of ref

In Vue 3, refs can be created in two ways:

// Options API
export default {
  data() {
    return {
      myRef: null
    }
  }
}

// Composition API
import { ref } from 'vue'

const myRef = ref(null)

When used in templates, simply add the ref attribute to an element or component:

<template>
  <div ref="myRef">This is a referenceable element</div>
  <ChildComponent ref="childComponent" />
</template>

Functional ref

Vue 3 introduces a new functional ref syntax, allowing the use of functions in ref bindings:

<template>
  <div :ref="(el) => { divElement = el }">Functional reference</div>
</template>

<script setup>
import { ref } from 'vue'

const divElement = ref(null)
</script>

This approach is particularly useful for dynamically generated refs, such as in v-for loops:

<template>
  <div v-for="item in items" :key="item.id" :ref="setItemRef">
    {{ item.text }}
  </div>
</template>

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

const items = ref([/* ... */])
const itemRefs = ref([])

const setItemRef = el => {
  if (el) {
    itemRefs.value.push(el)
  }
}

// Clear the refs array before updates
onBeforeUpdate(() => {
  itemRefs.value = []
})
</script>

Using ref on Components

When ref is used on a component, it points to the component instance:

<template>
  <ChildComponent ref="child" />
</template>

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

const child = ref(null)

onMounted(() => {
  // Access child component methods
  child.value.someMethod()
  
  // Access child component properties
  console.log(child.value.someProperty)
})
</script>

Controlling Exposed Content with expose

Vue 3 introduces the expose option to precisely control what a component exposes:

<!-- ChildComponent.vue -->
<script setup>
import { ref } from 'vue'

const internalState = ref('Private data')
const publicMethod = () => {
  console.log('This is a public method')
}

// Only expose publicMethod
defineExpose({
  publicMethod
})
</script>

Type Inference for ref with TypeScript

Vue 3 offers better TypeScript support, providing precise type hints for refs:

import { ref } from 'vue'
import type { HTMLInputElement } from 'vue'

const inputRef = ref<HTMLInputElement | null>(null)

onMounted(() => {
  if (inputRef.value) {
    inputRef.value.focus() // Has correct type hints
  }
})

Dynamic Components and ref

Refs on dynamic components behave differently and require special handling:

<template>
  <component :is="currentComponent" ref="dynamicComponent" />
</template>

<script setup>
import { ref, shallowRef } from 'vue'
import CompA from './CompA.vue'
import CompB from './CompB.vue'

const currentComponent = shallowRef(CompA)
const dynamicComponent = ref(null)

// The ref updates automatically when switching components
function toggleComponent() {
  currentComponent.value = currentComponent.value === CompA ? CompB : CompA
}
</script>

ref with Custom Directives

Custom directives can also work with refs:

<template>
  <div ref="target" v-custom-directive>Directive target</div>
</template>

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

const target = ref(null)

const vCustomDirective = {
  mounted(el) {
    console.log('Directive mounted', el === target.value) // true
  }
}
</script>

Using ref in Render Functions

In render functions, refs need to be passed as the second argument:

import { h, ref } from 'vue'

const myRef = ref(null)

export default {
  setup() {
    return () => h('div', { ref: myRef }, 'Reference in render function')
  }
}

ref with Teleport Component

Refs in Teleport components point to the teleported DOM element:

<template>
  <Teleport to="body">
    <div ref="teleported">Element to be teleported to body</div>
  </Teleport>
</template>

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

const teleported = ref(null)

onMounted(() => {
  console.log(teleported.value.parentNode) // body
})
</script>

Performance Considerations for ref

For large lists, using ref collections may impact performance. Vue provides optimized solutions for ref arrays:

<template>
  <div v-for="i in 1000" :key="i" :ref="setRef">Item {{ i }}</div>
</template>

<script setup>
import { ref } from 'vue'

const refs = ref([])

function setRef(el) {
  if (el) {
    refs.value.push(el)
  }
}
</script>

ref and SSR Compatibility

In server-side rendering (SSR) environments, ref behavior requires attention:

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

const clientOnlyRef = ref(null)

onMounted(() => {
  // Executes only on the client side
  console.log(clientOnlyRef.value)
})
</script>

ref with Suspense Component

In Suspense environments, refs need to wait for async components to resolve:

<template>
  <Suspense>
    <template #default>
      <AsyncComponent ref="asyncComp" />
    </template>
  </Suspense>
</template>

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

const asyncComp = ref(null)

// Needs to wait for Suspense to resolve
</script>

Debugging Tips for ref

During development, refs can be easily debugged:

import { ref } from 'vue'

const debugRef = ref(null)

// Add a watcher to observe ref changes
watch(debugRef, (newVal) => {
  console.log('ref value changed:', newVal)
}, { immediate: true })

Integrating ref with Third-Party Libraries

Refs provide convenient integration points with third-party libraries:

<template>
  <div ref="chartContainer"></div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'

const chartContainer = ref(null)

onMounted(() => {
  const chart = echarts.init(chartContainer.value)
  chart.setOption({/* ... */})
})
</script>

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.