반응형 기본 사항

반응형 기본 사항


1. 응답 상태 선언

reactive()다음 함수를 사용하여 반응 객체 또는 배열을 만들 수 있습니다 .

import {
    
     reactive } from 'vue'

const state = reactive({
    
     count: 0 })

반응형 개체는 실제로 일반 개체처럼 동작하는 JavaScript 프록시 입니다. 차이점은 Vue가 반응 객체 속성에 대한 액세스 및 변경 사항을 추적할 수 있다는 것입니다. 이에 대한 자세한 내용이 궁금하시다면 Reactive Systems in Depth 챕터 에서 설명하겠지만 여기에서 메인 가이드를 먼저 읽어보시길 권장합니다.

setup()구성 요소 템플릿에서 반응 상태를 사용하려면 함수에서 정의하고 반환 해야 합니다 .

import {
    
     reactive } from 'vue'

export default {
    
    
  // `setup` 是一个专门用于组合式 API 的特殊钩子函数
  setup() {
    
    
    const state = reactive({
    
     count: 0 })

    // 暴露 state 到模板
    return {
    
    
      state
    }
  }
}
<div>{
    
    {
    
     state.count }}</div>

state당연히 동일한 범위에서 업데이트된 함수를 정의하고 state다음과 함께 메서드로 노출할 수도 있습니다 .

import {
    
     reactive } from 'vue'

export default {
    
    
  setup() {
    
    
    const state = reactive({
    
     count: 0 })

    function increment() {
    
    
      state.count++
    }

    // 不要忘记同时暴露 increment 函数
    return {
    
    
      state,
      increment
    }
  }
}

노출된 메서드는 일반적으로 이벤트 리스너로 사용됩니다.

<button @click="increment">
  {
    
    {
    
     state.count }}
</button>

1.1<script setup>

함수 에서 setup()많은 상태와 메서드를 수동으로 노출하는 것은 지루한 작업입니다. 다행스럽게도 빌드 도구를 사용하면 이 작업을 더 쉽게 수행할 수 있습니다. SFC(Single File Components)를 사용하면 <script setup>코드를 크게 단순화할 수 있습니다.

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

const state = reactive({
    
     count: 0 })

function increment() {
    
    
  state.count++
}
</script>

<template>
  <button @click="increment">
    {
    
    {
    
     state.count }}
  </button>
</template>

1.2 DOM 업데이트 타이밍

반응형 상태를 변경하면 DOM도 자동으로 업데이트됩니다. 그러나 DOM 업데이트는 동기적이지 않다는 점에 유의해야 합니다. 대신 Vue는 업데이트 주기의 "다음 순간"까지 버퍼링하여 얼마나 많은 선언을 변경하더라도 각 구성 요소는 한 번만 업데이트하면 됩니다.

상태 변경 후 DOM 업데이트가 완료될 때까지 기다리려면 nextTick() 전역 API를 사용할 수 있습니다.

import {
    
     nextTick } from 'vue'

function increment() {
    
    
  state.count++
  nextTick(() => {
    
    
    // 访问更新后的 DOM
  })
}

1.3 깊은 응답성

Vue에서 상태는 기본적으로 심층 반응형입니다. 즉, 깊은 개체나 배열을 변경하더라도 변경 사항이 감지됩니다.

import {
    
     reactive } from 'vue'

const obj = reactive({
    
    
  nested: {
    
     count: 0 },
  arr: ['foo', 'bar']
})

function mutateDeeply() {
    
    
  // 以下都会按照期望工作
  obj.nested.count++
  obj.arr.push('baz')
}

얕은 반응 객체를 직접 만들 수도 있습니다 . 최상위 수준에서만 반응하며 일반적으로 일부 특수 시나리오에서만 필요합니다.

1.4 반응형 프록시 대 원시 객체

reactive()반환되는 것은 원래 객체와 같지 않은 원본 객체 의 프록시 라는 점에 주목할 가치가 있습니다 .

const raw = {
    
    }
const proxy = reactive(raw)

// 代理对象和原始对象不是全等的
console.log(proxy === raw) // false

프록시 객체만 반응형이며 원본 객체를 변경해도 업데이트가 트리거되지 않습니다. 따라서 Vue 반응 시스템의 모범 사례는 선언한 객체의 프록시 버전만 사용하는 것 입니다 .

프록시에 대한 일관된 액세스를 보장하기 위해 동일한 원본 객체에 대한 호출은 reactive()항상 동일한 프록시 객체를 반환하는 반면 기존 프록시 객체에 대한 호출은 reactive()자신을 반환합니다.

// 在同一个对象上调用 reactive() 会返回相同的代理
console.log(reactive(raw) === proxy) // true

// 在一个代理上调用 reactive() 会返回它自己
console.log(reactive(proxy) === proxy) // true

이 규칙은 중첩된 개체에도 적용됩니다. 깊은 응답성에 의존하는 반응 객체 내의 중첩 객체는 여전히 프록시입니다.

const proxy = reactive({
    
    })

const raw = {
    
    }
proxy.nested = raw

console.log(proxy.nested === raw) // false

1.5 reactive()제한 사항

reactive()API에는 두 가지 제한 사항이 있습니다.

  1. Map객체 유형(Object, Array 및 과 Set같은 컬렉션 유형 ) 에만 유효하며 stringnumberboolean같은 기본 유형에는 유효하지 않습니다 .

  2. Vue의 리액티브 시스템은 속성 액세스를 통해 추적되기 때문에 리액티브 객체에 대한 동일한 참조를 항상 유지해야 합니다. 이는 반응 객체를 임의로 "교체"할 수 없음을 의미합니다. 이렇게 하면 원래 참조에 대한 반응 연결이 손실될 수 있기 때문입니다.

    let state = reactive({
          
           count: 0 })
    
    // 上面的引用 ({ count: 0 }) 将不再被追踪(响应性连接已丢失!)
    state = reactive({
          
           count: 1 })
    

또한 반응 객체의 속성을 지역 변수에 할당하거나 분해하거나 해당 속성을 함수에 전달할 때 응답성을 잃게 됩니다.

const state = reactive({
    
     count: 0 })

// n 是一个局部变量,同 state.count
// 失去响应性连接
let n = state.count
// 不影响原始的 state
n++

// count 也和 state.count 失去了响应性连接
let {
    
     count } = state
// 不会影响原始的 state
count++

// 该函数接收一个普通数字,并且
// 将无法跟踪 state.count 的变化
callSomeFunction(state.count)

2. ref()반응 변수 정의

reactive()최종 분석에서 의 다양한 제한 사항은 JavaScript에 모든 값 유형에서 작동할 수 있는 "참조" 메커니즘이 없기 때문입니다. 이를 위해 Vue는 모든 값 유형을 사용할 수 있는 ref()반응형 참조를 생성할 수 있는 메서드를 제공합니다 .

import {
    
     ref } from 'vue'

const count = ref(0)

ref()들어오는 매개변수의 값을 .value다음 특성을 사용하여 ref 개체로 래핑합니다.

const count = ref(0)

console.log(count) // { value: 0 }
console.log(count.value) // 0

count.value++
console.log(count.value) // 1

반응 객체의 속성과 유사하게 ref .value속성도 반응적입니다. 동시에 값이 객체 유형인 경우 reactive()로 자동 변환됩니다 .value.

object 유형의 값을 포함하는 ref는 반응적으로 전체 개체를 대체할 수 있습니다.

const objectRef = ref({
    
     count: 0 })

// 这是响应式的替换
objectRef.value = {
    
     count: 1 }

ref는 반응성을 잃지 않고 함수로 전달되거나 일반 객체에서 해체됩니다.

const obj = {
    
    
  foo: ref(1),
  bar: ref(2)
}

// 该函数接收一个 ref
// 需要通过 .value 取值
// 但它会保持响应性
callSomeFunction(obj.foo)

// 仍然是响应式的
const {
    
     foo, bar } = obj

즉, ref()임의의 값에 대한 "참조"를 생성하고 응답성을 잃지 않고 전달할 수 있습니다. 이 기능은 논리를 복합 함수 로 추출하는 데 자주 사용되기 때문에 중요합니다.

2.1 템플릿에서 참조 풀기

참조가 템플릿의 최상위 속성으로 액세스되면 자동으로 "언래핑"되므로 사용할 필요가 없습니다 .value. 다음은 이전의 반대 예이며 다음 ref()으로 대체되었습니다.

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

const count = ref(0)

function increment() {
    
    
  count.value++
}
</script>

<template>
  <button @click="increment">
    {
    
    {
    
     count }} <!-- 无需 .value -->
  </button>
</template>

자동 "언래핑"은 ref가 템플릿 렌더링 컨텍스트의 최상위 속성인 경우에만 적용됩니다. 예를 들어 foo는 최상위 속성이지만 object.foo는 그렇지 않습니다.

그래서 우리는 다음 객체를 제공합니다.

const object = {
    
     foo: ref(1) }

표면 표현식이 예상대로 작동 하지 않습니다 .

{
    
    {
    
     object.foo + 1 }}

렌더링된 결과는 ref 객체 [object Object]이므로 one 이 됩니다 . 최상위 속성으로 변경하여 이 문제를 해결할 object.foo수 있습니다 .foo

const {
    
     foo } = object
{
    
    {
    
     foo + 1 }}

이제 렌더링된 결과는 입니다 2.

ref가 { { }}텍스트 보간에 의해 계산된 최종 값(예: 기호)인 경우에도 래핑이 해제됩니다. 따라서 아래 렌더링된 결과는 다음과 같습니다 1.

{
    
    {
    
     object.foo }}

이것은 텍스트 보간을 위한 편의 기능으로 { { object.foo.value }}.

2.2 응답 객체에서 ref 압축 풀기

a가 ref반응 객체 내에 중첩되면 속성으로 액세스하거나 변경할 때 자동으로 래핑이 해제되므로 일반 속성처럼 작동합니다.

const count = ref(0)
const state = reactive({
    
    
  count
})

console.log(state.count) // 0

state.count = 1
console.log(count.value) // 1

기존 ref와 연결된 속성에 새 ref를 할당하면 이전 ref를 대체합니다.

const otherCount = ref(2)

state.count = otherCount
console.log(state.count) // 2
// 原始 ref 现在已经和 state.count 失去联系
console.log(count.value) // 1

Ref 언래핑은 심층 반응 객체 내부에 중첩된 경우에만 발생합니다. 얕은 반응 객체 의 속성으로 액세스할 때 래핑되지 않습니다 .

2.2.1 배열 및 컬렉션 유형의 참조 풀기

반응 객체와 달리 ref는 반응 배열 또는 이와 같은 기본 컬렉션 유형의 요소로 Map액세스할 때 래핑 해제되지 않습니다 .

const books = reactive([ref('Vue 3 Guide')])
// 这里需要 .value
console.log(books[0].value)

const map = reactive(new Map([['count', ref(0)]]))
// 这里需要 .value
console.log(map.get('count').value)

3. 반응형 구문 설탕

.value일반 JavaScript 변수와 비교할 때 ref의 값을 얻기 위해 상대적으로 번거로운 것을 사용해야 합니다 . 이는 JavaScript 언어의 한계로 인해 제한되는 단점입니다. .value그러나 컴파일 타임 변환을 사용하면 컴파일러가 . Vue는 이전 "카운터" 예제를 다음과 같이 작성할 수 있는 컴파일 타임 변환을 제공합니다.

<script setup>
let count = $ref(0)

function increment() {
    
    
  // 无需 .value
  count++
}
</script>

<template>
  <button @click="increment">{
    
    {
    
     count }}</button>
</template>

Supongo que te gusta

Origin blog.csdn.net/klylove/article/details/126602278
Recomendado
Clasificación