목차
1. 반응형 소스 코드
1. 반응형
2、接着看工厂方法createReactiveObject
二、baseHandlers
1、baseHandlers
웹 프론트엔드 View.js Vue3 반응형 핵심 반응형 소스 코드 분석

Vue3 반응형 핵심 반응형 소스 코드 분석

May 23, 2023 pm 02:04 PM
vue3 reactive

1. 반응형 소스 코드

1. 반응형

소스 코드 경로: packages/reactivity/src/reactive.tspackages/reactivity/src/reactive.ts

export function reactive(target: object) {
  // if trying to observe a readonly proxy, return the readonly version.
  // 是否是只读响应式对象
  if (isReadonly(target)) {
    return target
  }
  return createReactiveObject(
    target,
    false,
    mutableHandlers,
    mutableCollectionHandlers,
    reactiveMap
  )
}
로그인 후 복사

当我们执行reactive({})的时候,会执行createReactiveObject这个工厂方法,返回一个响应式对象。

2、接着看工厂方法createReactiveObject

源码路径:packages/reactivity/src/reactive.ts

function createReactiveObject(
  target: Target,
  isReadonly: boolean,
  baseHandlers: ProxyHandler<any>,
  collectionHandlers: ProxyHandler<any>,
  proxyMap: WeakMap<Target, any>
) {
  // 仅对对象类型有效(对象、数组和 Map、Set 这样的集合类型),而对 string、number 和 boolean 这样的 原始类型 无效。
  if (!isObject(target)) {
    if (__DEV__) {
      console.warn(`value cannot be made reactive: ${String(target)}`)
    }
    return target
  }
  // target is already a Proxy, return it.
  // exception: calling readonly() on a reactive object
  if (
    target[ReactiveFlags.RAW] &&
    !(isReadonly && target[ReactiveFlags.IS_REACTIVE])
  ) {
    return target
  }
  // target already has corresponding Proxy
  const existingProxy = proxyMap.get(target)
  if (existingProxy) {
    return existingProxy
  }
  // only specific value types can be observed.
  const targetType = getTargetType(target)
  if (targetType === TargetType.INVALID) {
    return target
  }
  const proxy = new Proxy(
    target,
    targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers
  )
  proxyMap.set(target, proxy)
  return proxy
}
로그인 후 복사

仅对对象类型有效(对象、数组和 Map、Set 这样的集合类型),而对 string、number 和 boolean 这样的 原始类型 无效。

if (!isObject(target)) {
    if (__DEV__) {
      console.warn(`value cannot be made reactive: ${String(target)}`)
    }
    return target
}
로그인 후 복사

如果 target 已经是一个代理对象了,那么直接返回 target

if (
    target[ReactiveFlags.RAW] &&
    !(isReadonly && target[ReactiveFlags.IS_REACTIVE])
  ) {
    return target
}
로그인 후 복사

如果 target 已经有对应的代理对象了,那么直接返回代理对象

const existingProxy = proxyMap.get(target) // 存储响应式对象
if (existingProxy) {
    return existingProxy
}
로그인 후 복사

对于不能被观察的类型,直接返回 target

const targetType = getTargetType(target)
if (targetType === TargetType.INVALID) {
    return target
}
로그인 후 복사
// getTargetType源码
function getTargetType(value: Target) {
  return value[ReactiveFlags.SKIP] || !Object.isExtensible(value) // 不可扩展
    ? TargetType.INVALID
    : targetTypeMap(toRawType(value))
}

// ReactiveFlags枚举
export const enum ReactiveFlags {
  // 用于标识一个对象是否不可被转为代理对象,对应的值是 __v_skip 
  SKIP = &#39;__v_skip&#39;, 
  // 用于标识一个对象是否是响应式的代理,对应的值是 __v_isReactive
  IS_REACTIVE = &#39;__v_isReactive&#39;, 
  // 用于标识一个对象是否是只读的代理,对应的值是 __v_isReadonly
  IS_READONLY = &#39;__v_isReadonly&#39;,
  // 用于标识一个对象是否是浅层代理,对应的值是 __v_isShallow
  IS_SHALLOW = &#39;__v_isShallow&#39;,
  // 用于保存原始对象的 key,对应的值是 __v_raw
  RAW = &#39;__v_raw&#39;
}

// targetTypeMap
function targetTypeMap(rawType: string) {
  switch (rawType) {
    case &#39;Object&#39;:
    case &#39;Array&#39;:
      return TargetType.COMMON
    case &#39;Map&#39;:
    case &#39;Set&#39;:
    case &#39;WeakMap&#39;:
    case &#39;WeakSet&#39;:
      return TargetType.COLLECTION
    default:
      return TargetType.INVALID
  }
}

// toRawType
export const toRawType = (value: unknown): string => {
  // extract "RawType" from strings like "[object RawType]"
  return toTypeString(value).slice(8, -1)
}
로그인 후 복사

创建响应式对象(核心代码)

const proxy = new Proxy(
    target,
    targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers
)
로그인 후 복사

接下来将重点讲解baseHandlers这个回调函数。

二、baseHandlers

1、baseHandlers

baseHandlersmutableHandlers, 来自于 baseHandlers

export const mutableHandlers: ProxyHandler<object> = {
  get,
  set,
  deleteProperty,
  has,
  ownKeys
}
로그인 후 복사

reactive({})</code를 실행할 때 > 시간이 지나면 팩토리 메소드 <code>createReactiveObject가 실행되고 반응형 객체가 반환됩니다.

Vue3 반응형 핵심 반응형 소스 코드 분석2. 다음으로, 팩토리 메소드 createReactiveObject를 살펴보세요

소스 코드 경로: packages/reactivity/src/reactive.ts

const get = /*#__PURE__*/ createGetter()

function createGetter(isReadonly = false, shallow = false) {
  // 闭包返回 get 拦截器方法
  return function get(target: Target, key: string | symbol, receiver: object) {
       // 如果访问的是 __v_isReactive 属性,那么返回 isReadonly 的取反值
    if (key === ReactiveFlags.IS_REACTIVE) {
      return !isReadonly
      // 如果访问的是 __v_isReadonly 属性,那么返回 isReadonly 的值
    } else if (key === ReactiveFlags.IS_READONLY) {
      return isReadonly
      // 如果访问的是 __v_isShallow 属性,那么返回 shallow 的值
    } else if (key === ReactiveFlags.IS_SHALLOW) {
      return shallow
      // 如果访问的是 __v_raw 属性,那么返回 target
    } else if (
      key === ReactiveFlags.RAW &&
      receiver ===
        (isReadonly
          ? shallow
            ? shallowReadonlyMap
            : readonlyMap
          : shallow
          ? shallowReactiveMap
          : reactiveMap
        ).get(target)
    ) {
      return target
    }

    // target是否是数组
    const targetIsArray = isArray(target)

    if (!isReadonly) { // 可读
      // 如果是数组,并且访问的是数组的一些方法,那么返回对应的方法
      
    /**
     * Vue3中使用 arrayInstrumentations对数组的部分方法做了处理,为什么要这么做呢? 
     * 对于 push、pop、 shift、 unshift、 splice 这些方法,
     * 写入和删除时底层会获取当前数组的length属性,如果我们在effect中使用的话,
     * 会收集length属性的依赖,当使用这些api是也会更改length,就会造成死循环:
     * */
      if (targetIsArray && hasOwn(arrayInstrumentations, key)) {
        // 返回重写的push、pop、 shift、 unshift、 splice &#39;includes&#39;, &#39;indexOf&#39;, &#39;lastIndexOf&#39;
        return Reflect.get(arrayInstrumentations, key, receiver)
      }
      // 如果访问的是 hasOwnProperty 方法,那么返回 hasOwnProperty 方法
      if (key === &#39;hasOwnProperty&#39;) {
        return hasOwnProperty
      }
    }

    // 获取 target 的 key 属性值
    const res = Reflect.get(target, key, receiver)

    // 如果是内置的 Symbol,或者是不可追踪的 key,那么直接返回 res
    if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
      return res
    }

    // 如果不是只读的,那么进行依赖收集
    if (!isReadonly) {
      track(target, TrackOpTypes.GET, key)
    }

    // 如果是浅的,那么直接返回 res
    if (shallow) {
      return res
    }
    // 如果 res 是 ref,对返回的值进行解包
    if (isRef(res)) {
      // ref unwrapping - skip unwrap for Array + integer key.
      return targetIsArray && isIntegerKey(key) ? res : res.value
    }
    // 如果 res 是对象,递归代理
    if (isObject(res)) {
      // Convert returned value into a proxy as well. we do the isObject check
      // here to avoid invalid value warning. Also need to lazy access readonly
      // and reactive here to avoid circular dependency.
      return isReadonly ? readonly(res) : reactive(res)
    }

    return res
  }
}
로그인 후 복사

객체 유형(객체, 배열 및 컬렉션 유형)에만 유효합니다. Map 및 Set )이며 문자열, 숫자 및 부울과 같은 기본 유형에는 유효하지 않습니다.

  if (targetIsArray && hasOwn(arrayInstrumentations, key)) {
    // 返回重写的push、pop、 shift、 unshift、 splice &#39;includes&#39;, &#39;indexOf&#39;, &#39;lastIndexOf&#39;
    return Reflect.get(arrayInstrumentations, key, receiver)
  }
로그인 후 복사

대상이 이미 프록시 객체인 경우 대상을 직접 반환

const arrayInstrumentations = /*#__PURE__*/ createArrayInstrumentations()

function createArrayInstrumentations() {
  const instrumentations: Record<string, Function> = {}
  // instrument length-altering mutation methods to avoid length being tracked
  // which leads to infinite loops in some cases (#2137)
  ;([&#39;push&#39;, &#39;pop&#39;, &#39;shift&#39;, &#39;unshift&#39;, &#39;splice&#39;] as const).forEach(key => {
    instrumentations[key] = function (this: unknown[], ...args: unknown[]) {
      // 由于上面的方法会改变数组长度,因此暂停收集依赖,不然会导致无限递归
      console.log(&#39;----自定义push等入口:this, args, key&#39;);
      pauseTracking()
      console.log(&#39;----自定义push等暂停收集依赖&执行开始&#39;)
      // 调用原始方法
      const res = (toRaw(this) as any)[key].apply(this, args)
      console.log(&#39;----自定义push等暂停收集依赖&执行结束&#39;)
      //复原依赖收集
      resetTracking()
      return res
    }
  })
  return instrumentations
}
로그인 후 복사
대상에 해당 프록시 객체가 이미 있는 경우 프록시 객체를 직접 반환

let arr = [1,2,3]
let obj = {
    &#39;push&#39;: function(...args) {
        // 暂停收集依赖逻辑
        return Array.prototype.push.apply(this, [...args])
        // 启动收集依赖逻辑
    }
}
let proxy = new Proxy(arr, {	
   get: function (target, key, receiver) {
       console.log(&#39;get的key为 ===>&#39; + key);
       let res = &#39;&#39;;
       if(key === &#39;push&#39;) { //重写push
        res = Reflect.get(obj, key, receiver)
       } else {
        res = Reflect.get(target, key, receiver)
       }
       return res
   },
   set(target, key, value, receiver){
       console.log(&#39;set的key为 ===>&#39; + key, value);
       return Reflect.set(target, key, value, receiver);
   }
})

proxy.push(&#39;99&#39;)
로그인 후 복사

관찰할 수 없는 유형의 경우 대상을 직접 반환

// 如果是内置的 Symbol,或者是不可追踪的 key,那么直接返回 res
    if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
        return res;
    }
로그인 후 복사
// 如果不是只读的,那么进行依赖收集
    if (!isReadonly) {
        track(target, "get" /* TrackOpTypes.GET */, key);
    }
로그인 후 복사

반응형 생성 객체(핵심 코드)

if (shallow) {
  return res;
}
로그인 후 복사

다음으로 콜백 함수 baseHandlers에 집중하겠습니다.

2.baseHandlersVue3 반응형 핵심 반응형 소스 코드 분석

1.baseHandlers

baseHandlersbaseHandlers 파일에서 오는 mutableHandlers입니다.

mutableHandlers의 소스 코드는 다음과 같으며 각각 get, set, deleteProperty, has 및 ownKeys를 프록시합니다.

 // 如果 res 是 ref,对返回的值进行解包
    if (isRef(res)) {
        // 对于数组和整数类型的 key,不进行解包
        return targetIsArray && isIntegerKey(key) ? res : res.value;
    }
로그인 후 복사
이러한 인터셉터의 구체적인 구현을 살펴보겠습니다.

(1), get

 // 如果 res 是对象,那么对返回的值进行递归代理
    if (isObject(res)) {
        return isReadonly ? readonly(res) : reactive(res);
    }
로그인 후 복사

의 프록시 대상이 배열인 경우 'push', 'pop', 'shift', 'unshift', 'splice' 메소드는 배열의 길이를 변경합니다. 그러면 무한 재귀가 발생하므로 먼저 종속성 수집을 일시 중지해야 하므로 위의 배열 메서드를 가로채서 다시 작성했습니다

const set = /*#__PURE__*/ createSetter()

function createSetter(shallow = false) {
  // 返回一个set方法
  return function set(
    target: object,
    key: string | symbol,
    value: unknown,
    receiver: object
  ): boolean {
    let oldValue = (target as any)[key] // 获取旧值
    //  如果旧值是只读的,并且是 ref,并且新值不是 ref
    if (isReadonly(oldValue) && isRef(oldValue) && !isRef(value)) {
      return false
    }
    if (!shallow) { // 非shallow
      // 新值非shallow && 非只读
      if (!isShallow(value) && !isReadonly(value)) {
        // 获取新旧值的原始值
        oldValue = toRaw(oldValue)
        value = toRaw(value)
      }
      // 代理对象非数组 & 旧值是ref & 新值非ref
      if (!isArray(target) && isRef(oldValue) && !isRef(value)) {
        oldValue.value = value
        return true
      }
    } else {
      // in shallow mode, objects are set as-is regardless of reactive or not
    }
    console.log(&#39;----set&#39;, target, key, value)

    // 是数组 & key是整型数字 ? 
    // 如果 key 小于数组的长度,那么就是有这个 key : 
    // 如果不是数组,那么就是普通对象,直接判断是否有这个 key
    // 数组会触发两次set: index和新增的值 和 &#39;length&#39;和新增之后的数组长度
    const hadKey =
      isArray(target) && isIntegerKey(key)
        ? Number(key) < target.length
        : hasOwn(target, key) 
    // 设置key-value 
    const result = Reflect.set(target, key, value, receiver)
    // don&#39;t trigger if target is something up in the prototype chain of original
    // 如果目标对象是原始数据的原型链中的某个元素,则不会触发依赖收集
    if (target === toRaw(receiver)) {
      if (!hadKey) {// 如果没有这个 key,那么就是新增了一个属性,触发 add 事件
        trigger(target, TriggerOpTypes.ADD, key, value)
      } else if (hasChanged(value, oldValue)) { // // 如果有这个 key,那么就是修改了一个属性,触发 set 事件
        trigger(target, TriggerOpTypes.SET, key, value, oldValue)
      }
    }
    // 返回结果,这个结果为 boolean 类型,代表是否设置成功
    return result
  }
}
로그인 후 복사

다시 작성된 코드:

let oldValue = target[key];
로그인 후 복사

다음 그림은 실행 결과입니다.

다음 코드로 이해할 수 있습니다.

// 如果旧值是只读的,并且是 ref,并且新值不是 ref,那么直接返回 false,代表设置失败
    if (isReadonly(oldValue) && isRef(oldValue) && !isRef(value)) {
        return false;
    }
로그인 후 복사
특수 속성에 대한 종속성 컬렉션 없음

rrreee

이 단계는 Symbol.iterator, Symbol.toStringTag와 같은 기본 기호 유형 속성과 같은 일부 특수 속성을 필터링하는 것입니다. 이러한 속성은 내장되어 있고 변경되지 않으므로 종속성 수집이 필요하지 않습니다.

proto

, __v_isRef, __isVue와 같은 추적할 수 없는 속성도 있습니다. 🎜종속성 수집🎜rrreee🎜Shallow는 수행되지 않습니다. 재귀 에이전트는 🎜rrreee🎜 반환 값을 언팩합니다. 🎜rrreee🎜 이 단계는 ref 상황을 처리하는 것입니다. 배열이고 키가 정수 유형이면 압축을 풀 필요가 없습니다. 반응형은 반응성이 뛰어나므로 ref🎜🎜객체의 재귀 프록시🎜rrreee🎜🎜(2) 속성을 사용하여 압축을 풀어야 합니다. set의 프록시🎜🎜rrreee🎜기본 논리: 🎜🎜이전 값 가져오기🎜rrreee🎜이전 값이 읽기 전용인지 확인🎜rrreee

위 내용은 Vue3 반응형 핵심 반응형 소스 코드 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. 크로스 플레이가 있습니까?
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

vue3+vite: src에서 이미지를 동적으로 가져오기 위해 require를 사용할 때 오류를 해결하는 방법 vue3+vite: src에서 이미지를 동적으로 가져오기 위해 require를 사용할 때 오류를 해결하는 방법 May 21, 2023 pm 03:16 PM

vue3+vite:src는 require를 사용하여 이미지를 동적으로 가져오고 vue3+vite는 여러 이미지를 동적으로 가져옵니다. vue3을 사용하는 경우 require는 이미지를 사용할 수 없습니다. imgUrl:require(' .../assets/test.png') 와 같은 vue2는 typescript가 require를 지원하지 않기 때문에 가져오므로 이를 해결하는 방법은 다음과 같습니다. waitimport를 사용합니다.

vue3 프로젝트에서tinymce를 사용하는 방법 vue3 프로젝트에서tinymce를 사용하는 방법 May 19, 2023 pm 08:40 PM

tinymce는 완전한 기능을 갖춘 리치 텍스트 편집기 플러그인이지만,tinymce를 vue에 도입하는 것은 다른 Vue 리치 텍스트 플러그인만큼 원활하지 않습니다.tinymce 자체는 Vue에 적합하지 않으며 @tinymce/tinymce-vue를 도입해야 합니다. 외국 서식 있는 텍스트 플러그인이며 중국어 버전을 통과하지 못했습니다. 공식 웹사이트에서 번역 패키지를 다운로드해야 합니다(방화벽을 우회해야 할 수도 있음). 1. 관련 종속성을 설치합니다. npminstalltinymce-Snpminstall@tinymce/tinymce-vue-S2. 중국어 패키지를 다운로드합니다. 3. 프로젝트 공용 폴더에 스킨과 중국어 패키지를 새로 만들고 다운로드합니다.

Vue3에서 페이지의 일부 콘텐츠를 새로 고치는 방법 Vue3에서 페이지의 일부 콘텐츠를 새로 고치는 방법 May 26, 2023 pm 05:31 PM

페이지를 부분적으로 새로 고치려면 로컬 구성 요소(dom)의 다시 렌더링만 구현하면 됩니다. Vue에서 이 효과를 얻는 가장 쉬운 방법은 v-if 지시어를 사용하는 것입니다. Vue2에서는 v-if 명령을 사용하여 로컬 DOM을 다시 렌더링하는 것 외에도 새 빈 구성 요소를 만들 수도 있습니다. 로컬 페이지를 새로 고쳐야 할 경우 이 빈 구성 요소 페이지로 점프한 다음 다시 돌아올 수 있습니다. 빈 원본 페이지의 beforeRouteEnter 가드. 아래 그림과 같이 Vue3.X에서 새로 고침 버튼을 클릭하여 빨간색 상자 안에 DOM을 다시 로드하고 해당 로딩 상태를 표시하는 방법입니다. Vue3.X의 scriptsetup 구문에 있는 구성 요소의 가드에는

Vue3가 마크다운을 구문 분석하고 코드 강조 표시를 구현하는 방법 Vue3가 마크다운을 구문 분석하고 코드 강조 표시를 구현하는 방법 May 20, 2023 pm 04:16 PM

Vue로 블로그 프론트엔드를 구현하려면 마크다운 파싱을 구현해야 합니다. 코드가 있는 경우 코드 하이라이팅을 구현해야 합니다. markdown-it, vue-markdown-loader,marked,vue-markdown 등과 같은 Vue용 마크다운 구문 분석 라이브러리가 많이 있습니다. 이 라이브러리는 모두 매우 유사합니다. 여기서는 Marked가 사용되었고, 코드 하이라이팅 라이브러리로 하이라이트.js가 사용되었습니다. 구체적인 구현 단계는 다음과 같습니다. 1. 종속 라이브러리를 설치합니다. vue 프로젝트에서 명령 창을 열고 다음 명령 npminstallmarked-save//marked를 입력하여 markdown을 htmlnpmins로 변환합니다.

vue3 프로젝트가 패키징되어 서버에 게시된 후 액세스 페이지가 공백으로 표시되는 문제를 해결하는 방법 vue3 프로젝트가 패키징되어 서버에 게시된 후 액세스 페이지가 공백으로 표시되는 문제를 해결하는 방법 May 17, 2023 am 08:19 AM

vue3 프로젝트가 패키징되어 서버에 게시되면 액세스 페이지에 공백 1이 표시됩니다. vue.config.js 파일의 publicPath는 다음과 같이 처리됩니다. const{defineConfig}=require('@vue/cli-service') module.exports=defineConfig({publicPath :process.env.NODE_ENV==='생산'?'./':'/&

Vue3에서 아바타를 선택하고 자르는 방법 Vue3에서 아바타를 선택하고 자르는 방법 May 29, 2023 am 10:22 AM

최종 효과는 VueCropper 컴포넌트 Yarnaddvue-cropper@next를 설치하는 것입니다. 위의 설치 값은 Vue2이거나 다른 방법을 사용하여 참조하려는 경우 공식 npm 주소: 공식 튜토리얼을 방문하세요. 컴포넌트에서 참조하고 사용하는 것도 매우 간단합니다. 여기서는 해당 컴포넌트와 해당 스타일 파일을 소개하기만 하면 됩니다. 여기서는 import{userInfoByRequest}from'../js/api만 소개하면 됩니다. 내 구성 요소 파일에서 import{VueCropper}from'vue-cropper&

vue3+ts+axios+pinia를 사용하여 무의미한 새로 고침을 달성하는 방법 vue3+ts+axios+pinia를 사용하여 무의미한 새로 고침을 달성하는 방법 May 25, 2023 pm 03:37 PM

vue3+ts+axios+pinia는 무의미한 새로 고침을 실현합니다. 1. 먼저 프로젝트에서 aiXos 및 pinianpmipinia를 다운로드합니다--savenpminstallaxios--save2. AxiosResponse}from"axios";importaxiosfrom'axios';import{ElMess

Vue3 재사용 가능한 구성 요소를 사용하는 방법 Vue3 재사용 가능한 구성 요소를 사용하는 방법 May 20, 2023 pm 07:25 PM

머리말 Vue든 React든, 여러 개의 반복되는 코드를 접하게 되면, 파일을 중복된 코드 덩어리로 채우는 대신, 이러한 코드를 어떻게 재사용할 수 있을지 고민해 보겠습니다. 실제로 vue와 React 모두 컴포넌트를 추출하여 재사용할 수 있지만, 작은 코드 조각이 발견되어 다른 파일을 추출하고 싶지 않은 경우, 이에 비해 React는 동일한에서 사용할 수 있습니다. 파일에서 해당 위젯을 선언합니다. 또는 다음과 같은 renderfunction을 통해 구현합니다. constDemo:FC=({msg})=>{returndemomsgis{msg}}constApp:FC=()=>{return(

See all articles