AI는 나에게 200줄의 코드로 단순화된 Vue 프레임워크를 작성하도록 가르쳤습니다.

AI는 미래의 최고의 교사입니다

최근에 Vue 기본에 대한 학습 자료를 준비하고 있었습니다. 이 기간 동안 저는 변덕스러웠습니다. 인기 있는 ChatGPT를 사용하여 학습 콘텐츠를 만들 수 있습니까? 사실 Vue 자체는 배우기 어렵지 않고, 특히 기본적인 사용법은 어렵지 않지만, Vue를 깊이 있게 마스터하고 싶다면 Vue의 소스 코드를 읽고 그 원리를 이해해야 합니다. 그러나 모든 사람이 Vue의 소스 코드를 읽을 시간과 인내심이 충분한 것은 아닙니다. 그래서 한 시간 이상 ChatGPT와 이야기하면서 Vue의 원칙을 보여주는 샘플 코드를 생성하도록 안내했습니다. 이 과정에서 나는 질문자 역할을 하고 ChatGPT가 내 질문에 따라 내가 원하는 코드를 생성하도록 합니다. 그 결과는 나에게 약간의 놀라움이었지만 완전히 예상하지 못한 것은 아니었다. 현재 AI의 급속한 발전 추세를 감안할 때 2024년이면 많은 직업이 AI로 대체될 것이라고 생각합니다. 미래는 AI가 인간을 대체하는 것이 아니라 AI를 사용할 줄 아는 사람이 AI를 사용할 줄 모르는 사람을 대체하는 것이라고 믿습니다. 다음으로 이 AI 조교의 수준을 함께 살펴보자.

이 문서는 주로 다음 내용에 대해 설명합니다.

  • AI가 입문에서 고급까지 Vue의 학습 개요를 나열하도록 합니다.
  • AI가 Vue 작동 방식을 설명하는 코드 예제를 제공하도록 시도하십시오.
  • Vue 라이프 사이클의 원리를 배우기 시작하세요
  • Vue 템플릿 구문 및 지시문의 원칙을 배웁니다.
  • Vue 데이터 모니터링 및 컴퓨팅 속성의 원리 알아보기
  • Vue 이벤트 처리 및 방법의 원리를 배웁니다.
  • Vue 슬롯(slot)의 원리를 알아본다.
  • 200줄의 코드로 간소화된 Vue 프레임워크 구현

AI가 Vue 학습의 개요를 나열하게 하십시오.

Vue를 체계적으로 배우기 위해서는 먼저 학습 개요를 작성해야 합니다. ChatGPT에 대한 나의 이해와 결합하여 내가 질문한 첫 번째 질문은 만족스러운 답변을 받았습니다. 다음은 내 질문의 원문입니다.

请列出一个Vue.js从入门到高级的学习大纲

ChatGPT의 답변은 다음과 같습니다.

当涉及Vue.js的学习大纲时,下面是一个从入门到高级的学习路线,涵盖了Vue.js的核心概念和高级主题:

  1. HTML, CSS 및 JavaScript 기본 사항
    • HTML 요소 및 태그
    • CSS 선택자 및 스타일
    • JavaScript 기본 구문 및 개념
  2. Vue.js 시작하기
    • Vue.js 소개 및 기능
    • Vue.js 설치 및 설정
    • Vue 인스턴스 및 수명 주기 후크
    • Vue 템플릿 구문 및 지시문
    • 데이터 바인딩 및 계산된 속성
    • 이벤트 처리 및 방법
  3. 뷰 컴포넌트
    • 구성요소의 기본 개념 및 구성
    • 부품 등록 및 사용
    • 구성 요소가 통신하는 방법(props, 이벤트 및 vuex)
    • 동적 및 비동기 구성 요소
    • 슬롯 및 범위 슬롯
  4. Vue 라우팅
    • Vue 라우터 설치 및 구성
    • 라우팅의 기본 사용법(탐색, 매개변수 전달)
    • 중첩 및 명명된 경로
    • 라우팅 가드 및 탐색 분석
  5. Vue 상태 관리(Vuex)
    • Vuex의 핵심 개념 및 사용 시나리오
    • Vuex 설치 및 구성
    • 상태, 돌연변이, 액션 및 Getter
    • 모듈성 및 네임스페이스
  6. 고급 뷰
    • 맞춤 지시어
    • 필터
    • 오염(Mixin)
    • 플러그인
    • 사용자 지정 전환 및 애니메이션
    • 서버측 렌더링(SSR)
  7. 외부 라이브러리와 Vue 통합
    • Axios를 사용한 HTTP 요청
    • Vue를 사용하여 타사 라이브러리(예: Chart.js, Google 지도 등)와 통합
    • Vue 및 Webpack으로 프로젝트 빌드
  8. Vue 모범 사례 및 성능 최적화
    • 구성 요소 분할 및 재사용
    • 계산된 속성 및 리스너의 현명한 사용
    • 불필요한 렌더링 방지
    • 비동기 구성 요소 및 코드 분할
    • 네트워크 요청 및 데이터 로드 최적화
  9. 뷰 테스트
    • 단위 테스트 및 종단 간 테스트의 개념
    • Vue 테스트 유틸리티를 사용한 단위 테스트
    • Cypress를 사용한 종단 간 테스트
  10. Vue 프로젝트 전투
    • Vue.js를 기반으로 완전한 애플리케이션 구축
    • Vue 라우터 및 Vuex를 사용한 상태 관리
    • 다른 라이브러리 및 도구 통합
    • 애플리케이션 테스트 및 최적화

请注意,这个学习大纲只是一个指导,你可以根据自己的学习进度和需求进行调整和扩展。此外,学习Vue.js最好通过实践项目和阅读官方文档来加深理解和掌握。

위 내용은 ChatGPT에 의해 생성된 것으로 어느 정도 보편성이 있지만 이 개요를 따르지는 않을 것입니다. 예를 들어, 많은 사람들은 Vue 데이터 양방향 바인딩의 사용이 매우 간단하다고 생각하지만 데이터 양방향 바인딩 구현을 시뮬레이션하는 것은 쉽지 않습니다. Vue 사용법을 배우기 위해 원칙을 숙달해야 하는 네 가지 주요 이유가 있습니다(이러한 이유는 ChatGPT에서도 생성됨).

  • 프레임워크에 대한 심층적 이해 : Vue의 원리를 배우면 Vue 프레임워크가 어떻게 설계되고 작동하는지 더 잘 이해할 수 있습니다. 여기에는 Vue의 반응형 데이터 바인딩, 가상 DOM 및 구성 요소 아키텍처와 같은 핵심 개념이 포함됩니다. 이러한 원칙을 이해하면 Vue를 더 잘 사용하고 애플리케이션을 보다 효율적으로 개발 및 디버그하는 데 도움이 될 수 있습니다.

  • 사용자 정의 확장 및 최적화 : Vue의 원칙을 마스터하면 사용자 정의 확장 및 최적화를 수행할 수 있습니다. 프로젝트 요구 사항에 따라 Vue의 지침, 플러그인, 필터 등을 사용자 지정할 수 있을 뿐만 아니라 성능을 최적화하고 리소스 소비를 줄일 수 있습니다. 원칙을 이해하면 다양한 개발 시나리오를 보다 유연하게 처리할 수 있습니다.

  • 문제 해결 및 디버깅 : 개발 과정에서 몇 가지 문제와 오류가 발생하는 것은 불가피합니다. Vue의 원리를 이해하면 더 빠르게 문제를 찾고 해결할 수 있습니다. 원칙을 이해하면 Vue의 내부에 대한 통찰력을 얻고 오류의 잠재적 원인을 식별하고 수정 조치를 취하는 데 도움이 될 수 있습니다.

  • 교차 프레임워크 학습 및 마이그레이션 : Vue의 원칙을 마스터하면 향후 다른 프런트 엔드 프레임워크를 배울 수 있는 기반을 마련할 수 있습니다. 많은 프론트엔드 프레임워크는 개념과 원리가 유사하기 때문에 Vue의 원리를 마스터하면 React, Angular 등과 같은 다른 프레임워크를 이해하고 배우는 것이 더 쉬울 것입니다. 또한 프로젝트를 다른 프레임워크로 마이그레이션해야 하는 경우 원칙을 이해하면 새 프레임워크의 작동 방식을 더 잘 이해할 수 있습니다.


AI가 Vue의 작동 방식을 설명하는 코드 예제를 제공하도록 합니다.

Vue에 구현된 기능을 시뮬레이트하는 샘플 코드를 생성할 수 있도록 ChatGPT에 질문을 하려면 어떻게 해야 하나요? 과거의 경험에 따르면 처음에 나는 다음과 같은 질문을 했다.

请给一个简单的JS代码实现的例子,说明Vue的生命周期及生命周期钩子的实现原理

ChatGPT의 답변은 다음과 같습니다.

以下是一个简单的JavaScript代码示例,展示了Vue的生命周期及生命周期钩子的实现原理:

<!DOCTYPE html>
<html>
<head>
  <title>Vue Lifecycle Example</title>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
  <div id="app">
    <p>{
   
   { message }}</p>
    <button @click="updateMessage">Update Message</button>
  </div>

  <script>
    var app = new Vue({
      el: '#app',
      data: {
        message: 'Hello, Vue!'
      },
      beforeCreate: function() {
        console.log('beforeCreate hook');
      },
      created: function() {
        console.log('created hook');
      },
      beforeMount: function() {
        console.log('beforeMount hook');
      },
      mounted: function() {
        console.log('mounted hook');
      },
      beforeUpdate: function() {
        console.log('beforeUpdate hook');
      },
      updated: function() {
        console.log('updated hook');
      },
      beforeDestroy: function() {
        console.log('beforeDestroy hook');
      },
      destroyed: function() {
        console.log('destroyed hook');
      },
      methods: {
        updateMessage: function() {
          this.message = 'Updated message';
        }
      }
    });
  </script>
</body>
</html>

분명히 이것은 우리가 원하는 Vue 수명 주기를 시뮬레이션하는 원리의 예가 아니라 Vue 수명 주기의 사용 예일 뿐입니다. 따라서 AI의 힌트 기술을 마스터하는 것이 매우 중요합니다. 미래에는 AI 프롬프터가 직업이 될 수도 있고 AI 프롬프팅 기술을 배우는 것은 오늘날 스마트폰을 사용하는 것처럼 생존 기술이 될 것입니다.


AI를 사용하여 Vue 수명 주기의 원리 학습

이전 코드를 통해 Vue의 수명 주기를 사용하는 방법을 이해할 수 있었습니다. 시뮬레이션을 용이하게 하기 위해 Vue의 선택적 API를 사용하고 시뮬레이션 사용의 샘플 코드가 다음과 같다고 가정하여 수명 주기 사용을 일부 조정합니다.

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello, Vue!'
  },
  beforeCreate: function() {
    console.log('beforeCreate hook');
  },
  created: function() {
    console.log('created hook');
  },
  beforeMount: function() {
    console.log('beforeMount hook');
  },
  mounted: function() {
    console.log('mounted hook');
  },
  beforeUpdate: function() {
    console.log('beforeUpdate hook');
  },
  updated: function() {
    console.log('updated hook');
  },
  render: function() {
    return '<p>' + this.message + '</p>';
  }
});

우리가 조정하는 것은  render 메소드로 대체하는  것이고 methods목적은  render 메소드가 반환한 내용을  app ID가 있는 DOM 요소에 렌더링하는 것입니다. render 메서드  에서  얻을 this.message 내용은  data 객체에 정의된  속성의 값입니다 message .

먼저 위의 기능을 구현하는 방법에 대해 생각해보자 핵심은 Vue 구성 객체의 el, data, beforeCreate, created, beforeMount, mounted, beforeUpdate, updated 및 render 속성을 구현하는 것입니다.

다음으로 ChatGPT가 위의 속성을 실현하는 방법을 살펴보겠습니다. 다음은 ChatGPT에 대한 프롬프트입니다.

请给出一段代码,模拟实现Vue.js类似生命周期效果的示例代码

ChatGPT의 답변은 다음과 같습니다.

以下是一个简单的JavaScript代码示例,模拟实现类似Vue.js生命周期的效果:

function Vue(options) {
  this.$options = options;

  if (typeof options.beforeCreate === 'function') {
    options.beforeCreate.call(this);
  }

  this._data = typeof options.data === 'function' ? options.data() : options.data;

  this._proxyData();

  if (typeof options.created === 'function') {
    options.created.call(this);
  }

  this.$mount(options.el);
}

Vue.prototype.$mount = function(el) {
  this.$el = document.querySelector(el);

  if (typeof this.$options.beforeMount === 'function') {
    this.$options.beforeMount.call(this);
  }

  this.render();

  if (typeof this.$options.mounted === 'function') {
    this.$options.mounted.call(this);
  }
};

Vue.prototype._proxyData = function() {
  var self = this;
  Object.keys(this._data).forEach(function(key) {
    Object.defineProperty(self, key, {
      get: function() {
        return self._data[key];
      },
      set: function(newValue) {
        self._data[key] = newValue;
        if (typeof self.$options.beforeUpdate === 'function') {
          self.$options.beforeUpdate.call(self);
        }
        self.render();
        if (typeof self.$options.updated === 'function') {
          self.$options.updated.call(self);
        }
      }
    });
  });
};

Vue.prototype.render = function() {
  if (typeof this.$options.render === 'function') {
    this.$el.innerHTML = this.$options.render.call(this);
  }
};

// 使用示例
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello, Vue!'
  },
  beforeCreate: function() {
    console.log('beforeCreate hook');
  },
  created: function() {
    console.log('created hook');
  },
  beforeMount: function() {
    console.log('beforeMount hook');
  },
  mounted: function() {
    console.log('mounted hook');
  },
  beforeUpdate: function() {
    console.log('beforeUpdate hook');
  },
  updated: function() {
    console.log('updated hook');
  },
  render: function() {
    return '<p>' + this.message + '</p>';
  }
});

이 예제에서는  Vue 생성자를 정의하여 Vue.js 수명 주기를 시뮬레이션합니다. 생성자는 구성 개체를 매개 변수로 받고 인스턴스화 프로세스 중에 다양한 수명 주기 후크 기능을 트리거합니다.

생성자에서 먼저 구성 객체에 후크 함수가 정의되어 있는지 확인  beforeCreate 하고  created 해당 시간에 호출합니다. 그런 다음 데이터 개체를 처리하고 구성 개체의  data 속성을  읽고 data 실행하여 함수인 경우 반환 값을 얻고 개체인 경우 값을 직접 할당한 다음  메서드를 통해 _proxyData 데이터 개체의 속성을  Vue 인스턴스에 프록시하여 데이터의 양방향 바인딩을 달성합니다.

다음으로 메서드에서  $mount 구성 개체에  beforeMount 후크  기능이 정의되어 있는지 판단 mounted 하고 해당 시간에 호출합니다. $mount 메서드  에서  render 메서드를 호출하여 지정된 DOM 요소에 템플릿을 렌더링합니다.

_proxyData 메서드  에서   인스턴스  Object.defineProperty 에 위임할 데이터 개체의 속성을  사용하고 속성의  메서드  에서 트리거  및  후크  를  사용  합니다. 즉, 데이터 개체의 속성이 변경되는 한 보기 업데이트가 트리거됩니다.VuesetbeforeUpdaterenderupdated

메서드 에서는  구성 객체에 함수가 정의되어 render 있는지 판단하고   함수  render 를 통해 렌더링된 콘텐츠를 얻은 다음   메서드에서   요소가  초기화되는 요소 $el 의  속성에 할당합니다  .innerHTML$el$mountdocument.querySelector

마지막으로 예제의 구성 개체를 사용하여  Vue 렌더링을 시뮬레이션하여 수명 주기 후크 기능을 인스턴스화하고 트리거하여 Vue.js와 유사한 각 수명 주기의 효과를 달성합니다.

코드에 대한 위의 설명도 ChatGPT에 의해 생성되며 몇 가지 설명을 추가했습니다. 이 분야에서 ChatGPT의 능력은 전문 과외 선생님들 못지않게 뛰어나다는 것을 알 수 있습니다.

위의 JavaScript 코드는 직접 실행할 수 없으며 코드를  lifecycle.js 파일로 저장한 후  index.html 웹 페이지를 생성하고 파일을 참조합니다. 웹 페이지의 코드는 다음과 같습니다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="./lifecycle.js"></script>
  </body>
</html>

이런 식으로  열어서 직접 index.html 실행  lifecycle.js한 다음 브라우저에서 렌더링 결과를 보고 콘솔에서 로그 출력을 볼 수 있습니다. 또한  app.message = 'ChatGPT' 제어 입력에 대한 데이터 바인딩 및 페이지 업데이트 메커니즘을 검증할 수 있습니다.


AI를 사용하여 Vue 템플릿 구문 및 지침의 원리 학습

위의 학습 경로에 따라 템플릿 구문 및 지침을 배우기 전에 사용을 쉽게 시뮬레이션할 수 있는 예제 코드도 제공합니다.

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello, Vue!',
    inputValue: 'ChatGPT'
  },
  template: `
    <div>
      <p>{
   
   { message }}</p>
      <input v-model="inputValue" type="text">
      <p v-text="inputValue"></p>
    </div>
  `
});

템플릿 및 지시문과 관련된 다음 HTML 스니펫에 중점을 둡니다.

<div>
  <p>{
   
   { message }}</p>
  <input v-model="inputValue" type="text">
  <p v-text="inputValue"></p>
</div>

이 HTML 조각 자체는 템플릿 구문과 두 개의 지시어를 사용하는 템플릿의 내용입니다. 템플릿 구문은 이고  지시어  는  { { message }}각각  입니다 .v-modelv-text

마찬가지로 누구나 먼저 구현 방법에 대해 생각한 다음 ChatGPT가 템플릿 구문 및 지침을 구현하는 방법을 봅니다.다음은 내가 준 프롬프트입니다.

请给出一段代码,模拟实现Vue.js类似模板语法和指令的示例代码

ChatGPT의 답변은 다음과 같습니다.

以下是一个简单的JavaScript代码示例,模拟实现类似Vue.js的模板语法和指令:

function Vue(options) {
  this.$options = options;
  this._data = typeof options.data === 'function' ? options.data() : options.data;
  this._compileTemplate();
}

Vue.prototype._compileTemplate = function() {
  var self = this;
  var template = this.$options.template || '';

  var evalExpression = function(expression) {
    with (self._data) return eval(expression);
  }

  var compiledTemplate = template.replace(/\{\{(.*?)\}\}/g, function(match, expression) {
    var value = evalExpression(expression);
    return value !== undefined ? value : '';
  });

  var element = document.querySelector(this.$options.el);
  element.innerHTML = compiledTemplate.trim();

  element.querySelectorAll('[v-model]').forEach(function(element) {
    var value = element.getAttribute('v-model');
    element.value = self._data[value];
    element.addEventListener('input', function(event) {
      self._data[value] = event.target.value;
    });
  });

  element.querySelectorAll('[v-text]').forEach(function(element) {
    var value = element.getAttribute('v-text');
    element.textContent = self._data[value];
  });
};

// 使用示例
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello, Vue!',
    inputValue: 'ChatGPT'
  },
  template: `
    <div>
      <p>{
   
   { message }}</p>
      <input v-model="inputValue" type="text">
      <p v-text="inputValue"></p>
    </div>
  `
});

이 예제에서는  Vue 생성자를 정의하여 Vue.js의 템플릿 구문 및 지시문을 시뮬레이트합니다. 생성자는 구성 개체를 인수로 받고 인스턴스화하는 동안 템플릿을 컴파일합니다.

이 메서드 에서는  _compileTemplate 먼저 구성 개체에서 템플릿 문자열을 가져오고 정규식을 사용하여  { { expression }} 부품을 일치시킵니다. 그런 다음 함수를 사용하여  eval 식을 동적으로 평가하고 값을 다시 템플릿 문자열로 대체합니다. 다음으로 구성 개체의 속성에 따라 해당 DOM 요소를 얻고  el 컴파일된 템플릿 문자열을  innerHTML 요소의 속성에 할당합니다.

그런 다음  메소드를 통해 속성이 있는 querySelectorAll 모든  v-model 요소를 ​​가져오고 각 요소를 반복합니다. 순회하는 동안 지시문을 구문 분석하고  model 요소의 값을 해당 데이터 속성 값으로 설정하고   간단한 양방향 바인딩을 input 위한 이벤트 리스너를  추가합니다.inputValue

다음으로   메소드를 통해 속성이 있는 querySelectorAll 모든 요소를 ​​가져오고  각 요소를 반복합니다. v-text순회하는 동안 지시문을 구문 분석  text 하고 요소의 텍스트 콘텐츠를 해당 데이터 속성 값으로 설정합니다. inputValue 참고: 이 지시문에 대해 양방향 바인딩을 구현하지 않았습니다  .

마지막으로 예제의 구성 개체를 사용하여 인스턴스화  Vue하고 템플릿 문자열을 전달합니다. 템플릿 구문 분석 및 지침 실행을 시뮬레이션하여 Vue.js와 유사한 템플릿 구문 및 지침의 효과를 얻었습니다. 효과를 보려면 브라우저에서 페이지를 여십시오  index.html .

위 코드는 ChatGPT에서 완전히 생성되지 않습니다. 디버깅 프로세스 중에 정상적으로 실행하려면 두 가지 문제를 수정해야 하기 때문입니다.

  • 첫 번째 문제는 ChatGPT가 동적 으로  eval 표현식을 평가하기 위해 함수를  직접 사용하고자 한다는 것입니다  .ChatGPT에서 생성된 코드는  문자열인  eval(expression)입니다   .  함수를  직접 호출하여  얻은 값은  전역 객체에 정의된 속성이 없고   표현식의 원래 의도가   객체의  속성 값을 얻는  것이기  때문에 오류를 보고합니다  . 이를 위해   state 를  통해  전역 객체를 설정하는   기능을  추가하여  값을 올바르게 얻을 수 있도록 했습니다. 그러나   엄격 모드에서 문장을 사용하는 것은 권장되지 않으므로 최적의 솔루션이 아니므로 관심 있는 학생들은 최적의 솔루션을 공부할 수 있습니다.expression" message "messageevalmessagemessage{ { message }}this._datamessageevalExpressionwiththis._datathis._data.messagewith

  • querySelectorAll('[v-]') 두 번째 문제는 ChatGPT가 동시 획득  v-model 과  명령 v-text 의 내용을 사용하고자  하지만 실제 디버깅 과정에서 획득할 수 없다는 점입니다. 그래서 나는 그것을 두 개의 문장으로 분해했습니다. querySelectorAll('[v-model]') 그리고  querySelectorAll('[v-text]') 각각 명령 내용을 얻습니다.

ChatGPT에서 생성된 코드를 아직 신뢰하지 않은 것을 볼 수 있습니다. 코드에 문제가 있음을 발견하면 질문할 수 있으며 죄송하다고 말한 다음 새 코드를 재생성합니다.업데이트된 코드가 올바른지 여부에 관계없이 다시 확인해야 합니다.


AI를 사용하여 Vue 데이터 모니터링 및 컴퓨팅 속성의 원리 학습

다음으로 배울 것은 여전히 ​​상대적으로 기본적인 데이터 모니터링 및 컴퓨팅 속성입니다.사실 이전 수명 주기의 예에는 데이터 양방향 바인딩이 포함되어 있습니다.데이터 모니터링 및 컴퓨팅 속성의 원칙은 데이터 양방향 바인딩과 매우 유사합니다.

마찬가지로 쉬운 시뮬레이션을 위해 먼저 사용 예제 코드를 제공합니다.

var app = new Vue({
  data: {
    message: 'Hello, Vue!',
    firstName: 'John',
    lastName: 'Doe'
  },
  computed: {
    fullName: function() {
      return this.firstName + ' ' + this.lastName;
    }
  },
  watch: {
    message: function(newValue) {
      console.log('Message changed:', newValue);
    }
  }
});

console.log(app.message);       // Output: Hello, Vue!
app.message = 'Hello, Vue.js!'; // Output: Message changed: Hello, Vue.js!
console.log(app.message);       // Output: Hello, Vue.js!
console.log(app.fullName);      // Output: John Doe
app.message = 'New message';    // Output: Message changed: New message

샘플 코드에서 볼 수 있듯이 구성 개체에는  computed 및  watch 속성이 추가되었으며 속성 변경을 모니터링하기 위해 계산된 속성  fullName과  message 기능을 각각 정의합니다.

모두가 먼저 스스로 구현하는 방법에 대해 생각한 다음 ChatGPT가 데이터 모니터링 및 계산 속성을 구현하는 방법을 확인하십시오.다음은 내가 준 프롬프트입니다.

请给出一段代码,模拟实现Vue.js类似数据监听和计算属性的示例代码

ChatGPT의 답변은 다음과 같습니다.

要模拟实现Vue.js类似数据监听和计算属性的功能,可以使用Object.defineProperty来定义属性的get和set方法,并使用watch函数来监听属性的变化。以下是一个示例代码:

function Vue(options) {
  this._data = options.data;
  this._computed = options.computed;
  this._watch = options.watch;

  this._proxyData();
  this._createComputed();
  this._createWatchers();
}

Vue.prototype._proxyData = function() {
  var self = this;
  Object.keys(this._data).forEach(function(key) {
    Object.defineProperty(self, key, {
      get: function() {
        return self._data[key];
      },
      set: function(newValue) {
        self._data[key] = newValue;
      }
    });
  });
};

Vue.prototype._createComputed = function() {
  var self = this;
  var computed = this._computed || {};

  Object.keys(computed).forEach(function(key) {
    Object.defineProperty(self, key, {
      get: function() {
        return computed[key].call(self);
      }
    });
  });
};

Vue.prototype._createWatchers = function() {
  var self = this;
  var watch = this._watch || {};

  Object.keys(watch).forEach(function(key) {
    var callback = watch[key]
    var value = self._data[key];

    Object.defineProperty(self._data, key, {
      get: function() {
        return value;
      },
      set: function(newValue) {
        value = newValue;
        callback.call(self, newValue);
      }
    });
  });
};

// 使用示例
var app = new Vue({
  data: {
    message: 'Hello, Vue!',
    firstName: 'John',
    lastName: 'Doe'
  },
  computed: {
    fullName: function() {
      return this.firstName + ' ' + this.lastName;
    }
  },
  watch: {
    message: function(newValue) {
      console.log('Message changed:', newValue);
    }
  }
});

console.log(app.message);       // Output: Hello, Vue!
app.message = 'Hello, Vue.js!'; // Output: Message changed: Hello, Vue.js!
console.log(app.message);       // Output: Hello, Vue.js!
console.log(app.fullName);      // Output: John Doe
app.message = 'New message';    // Output: Message changed: New message

이 예제에서는 ,  및 를  포함하는  옵션 개체를 Vue 사용하는 생성자를  정의합니다  .datacomputedwatch

_proxyData 메서드  에서  인스턴스의 속성 Object.defineProperty 에 대해  Vue 정의된  get 메서드를  사용하여  개체 set 에 위임합니다  ._data

메서드 에서는  객체를 _createComputed 순회하여  computed 계산된 각 속성에 대한 메서드를 정의하여  get일반 속성으로 사용할 수 있도록 합니다.

_createWatchers 메소드  에서  우리는 객체를 순회하고 watch 각 속성에 대한  객체의 속성 변경에 Object.defineProperty 모니터  객체를 사용 _data 하고 변경이 발생할 때 콜백 함수를 트리거합니다.

마지막으로 예제의 구성 객체를 사용하여  Vue계산 속성 및 모니터 속성의 함수를 인스턴스화하고 전달합니다 스크립트를 실행하여 구성 속성의 값을 읽고 변경함으로써 Vue.js와 유사한 데이터 모니터 및 계산 속성의 효과를 실현합니다.

이전과 마찬가지로 위의 코드는 ChatGPT에서 정확하게 생성되지 않습니다. 원래 생성된 코드에서 리스너 속성은   리스너 함수를 추가하기 위해 메소드를  호출  app.$watch('message', ...) 하는 명령문을  실행해야 합니다.  수정된 모니터링 방법은 공식 사용에 더 가깝습니다  .app$watchVue


AI를 사용하여 Vue 이벤트 처리 및 방법의 원리 학습

이벤트 처리는 컴포넌트 개발 프로세스에서 매우 중요한 부분입니다.다음으로 Vue의 이벤트 처리 및 메서드를 구현하는 메커니즘을 시뮬레이션합니다.다음은 쉬운 시뮬레이션을 위한 사용 예제 코드입니다.

var app = new Vue({
  data: {
    message: 'Hello, Vue!'
  },
  methods: {
    greet: function() {
      this.$emit('greet', this.message);
    },
    updateMessage: function(newMessage) {
      this.message = newMessage;
    }
  },
});

app.$on('greet', function(message) {
  console.log('Greet:', message);
});

app.greet(); // Output: Greet: Hello, Vue!
app.updateMessage('Hello, World!');
app.greet(); // Output: Greet: Hello, World!

샘플 코드에서 볼 수 있듯이 구성 개체는 인스턴스 메서드를 정의하기 위한 새 특성을 추가  하고  이벤트를 발생시키고 이벤트를 수신하기 위한 methods 기본 제공  $emit 및  메서드도 추가합니다.$on

다들 어떻게 구현해야 할지 먼저 생각해보고, ChatGPT가 어떻게 이벤트 처리와 메서드를 구현하는지 보시고 제가 드린 프롬프트는 다음과 같습니다.

请给出一段代码,模拟实现Vue.js类似事件处理和方法的示例代码

ChatGPT의 답변은 다음과 같습니다.

以下是一个简单的JavaScript代码示例,模拟实现类似Vue.js的事件处理和方法:

function EventBus() {
  this._events = {};
}

EventBus.prototype.on = function(eventName, callback) {
  if (!this._events[eventName]) {
    this._events[eventName] = [];
  }
  this._events[eventName].push(callback);
};

EventBus.prototype.emit = function(eventName, payload) {
  if (this._events[eventName]) {
    this._events[eventName].forEach(function(callback) {
      callback(payload);
    });
  }
};

function Vue(options) {
  this._data = typeof options.data === 'function' ? options.data() : options.data;
  this._methods = options.methods;
  this._eventBus = new EventBus();

  this._proxyData();
  this._proxyMethods();
}

Vue.prototype._proxyData = function() {
  var self = this;
  Object.keys(this._data).forEach(function(key) {
    Object.defineProperty(self, key, {
      get: function() {
        return self._data[key];
      },
      set: function(newValue) {
        self._data[key] = newValue;
      }
    });
  });
};

Vue.prototype._proxyMethods = function() {
  var self = this;
  var methods = this._methods;
  if (methods) {
    Object.keys(methods).forEach(function(key) {
      self[key] = methods[key].bind(self);
    });
  }
};

Vue.prototype.$emit = function(eventName, payload) {
  this._eventBus.emit(eventName, payload);
};

Vue.prototype.$on = function(eventName, callback) {
  this._eventBus.on(eventName, callback);
};

// 使用示例
var app = new Vue({
  data: {
    message: 'Hello, Vue!'
  },
  methods: {
    greet: function() {
      this.$emit('greet', this.message);
    },
    updateMessage: function(newMessage) {
      this.message = newMessage;
    }
  },
});

app.$on('greet', function(message) {
  console.log('Greet:', message);
});

app.greet(); // Output: Greet: Hello, Vue!
app.updateMessage('Hello, World!');
app.greet(); // Output: Greet: Hello, World!

이 예제에서는 먼저  EventBus 개체를 사용하여 이벤트 버스를 시뮬레이트합니다.  개체에는 이벤트를 수신하는 메서드와   이벤트를 발생시키는 메서드가 EventBus 있습니다  .onemit

Vue 생성자  에서  EventBus 인스턴스를 생성하고 속성에 할당합니다  _eventBus .

이 방법 에서는   데이터의 양방향 바인딩을 실현하기 위해 데이터 객체의 속성을 Vue 인스턴스에 프록시하는 데 _proxyData 사용합니다  .Object.defineProperty

메서드 에서  _proxyMethods 구성 개체의 메서드를 Vue 인스턴스에 바인딩하여 이러한 메서드를 인스턴스에서 직접 액세스하고 호출할 수 있습니다.

프로토타입 에서   및  메서드를 Vue 정의합니다   .  이 메소드는 이벤트를 발생시키는 데 사용되며 이벤트 이름과 선택적 데이터 페이로드라는 두 개의 매개변수를 수신합니다.  이 메서드는 이벤트를 수신하는 데 사용되며 이벤트 이름과 콜백 함수라는 두 가지 매개변수를 받습니다.$emit$on$emit$on

마지막으로 인스턴스를 생성  Vue 하고 기존  Vue 구성 개체  의 메서드는  트리거 이벤트 메서드를  greet 사용하여   콜백 함수를 트리거하고 메시지를 출력합니다. 그런 다음 메서드를 사용하여 인스턴스에서  이벤트를  수신하고   콜백 함수를 정의하여 메시지를 출력합니다. 이러한 방식으로 Vue.js와 유사한 이벤트를 던지고 받는 기능을 시뮬레이션합니다.$emitgreet$ongreet

이전과 마찬가지로 위의 코드는 ChatGPT에서 정확하게 생성되지 않습니다. 원래 생성된 코드에는 이벤트 발생 및 수신에 대한 모의 구현이 없습니다. ChatGPT에서 생성된 코드라는 새로운 프롬프트를 제공한  EventBus 다음 위의 샘플 코드를 얻기 위해 두 개의 코드 조각을 병합했습니다.


AI를 이용하여 Vue 슬롯(slot)의 원리를 학습

마지막으로 Vue의 슬롯에 대해 알아봅시다. 슬롯의 사용을 시뮬레이션하기 위해서는 먼저 Vue의 컴포넌트 선언을 시뮬레이션하고 컴포넌트에 슬롯을 정의한 다음 템플릿을 통해 컴포넌트를 가져오고 컴포넌트 슬롯의 내용을 설정해야 합니다.다음은 쉬운 시뮬레이션을 위한 사용 예제 코드입니다.

var HelloComponent = {
  data: function() {
    return {
      name: 'John'
    };
  },
  template: `
    <div>
      <h1>{
   
   { name }}</h1>
      <slot></slot>
    </div>
  `
};

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello, Vue!'
  },
  components: {
    HelloComponent
  },
  template: `
    <HelloComponent>
      <p>{
   
   { message }}</p>
    </HelloComponent>
  `
});

위의 샘플 코드에서는 구성 요소를 선언하고  HelloComponent 구성 요소의 템플릿에 슬롯을 추가한  slot 다음 응용 프로그램의 템플릿에 구성 요소를 도입  하고  콘텐츠를 HelloComponent 구성 요소의  슬롯으로 추가합니다.<p>{ { message }}</p>

코드 실행 결과는 다음 HTML 코드를 생성합니다.

<div id="app">
  <hellocomponent>
    <div>
      <h1>John</h1>
      <slot>
        <p>Hello, Vue!</p>
      </slot>
    </div>
  </hellocomponent>
</div>

코드 단순화를 위해 HelloComponent 두  slot 개의 노드가 여전히 유지됩니다. 다들 먼저 직접 구현하는 방법에 대해 생각한 다음 ChatGPT가 슬롯을 구현하는 방법을 확인하십시오.다음은 내가 준 프롬프트입니다.

请给出一段代码,模拟实现Vue.js类似插槽(slot)的示例代码

ChatGPT의 답변은 다음과 같습니다.

要模拟实现Vue.js类似插槽(slot)的功能,可以在组件定义中使用特殊的标记来表示插槽,并在组件实例中通过相应的属性将内容传递到插槽中。以下是一个示例代码:

function Vue(options) {
  this.$options = options;
  this._data = typeof options.data === 'function' ? options.data() : options.data;
  this._components = options.components || {};

  this._proxyData();
  this._compileTemplate();
  this._proxyComponents();
}

Vue.prototype._proxyData = function() {
  var self = this;
  Object.keys(this._data).forEach(function(key) {
    Object.defineProperty(self, key, {
      get: function() {
        return self._data[key];
      },
      set: function(newValue) {
        self._data[key] = newValue;
      }
    });
  });
};

Vue.prototype._compileTemplate = function() {
  var self = this;
  var el = this.$options.el
  var template = this.$options.template || '';

  var evalExpression = function(expression) {
    with (self) return eval(expression);
  }

  var compiledTemplate = template.replace(/\{\{(.*?)\}\}/g, function(match, expression) {
    var value = evalExpression(expression);
    return value !== undefined ? value : '';
  });

  var element = el ? document.querySelector(el) : document.createElement('div');
  element.innerHTML = compiledTemplate.trim();
  this.$el = el ? element : element.childNodes[0];
};

Vue.prototype._proxyComponents = function() {
  var self = this;
  var components = this._components;

  Object.keys(components).forEach(function(componentName) {
    var component = new Vue(components[componentName]);
    self.$el.querySelectorAll(componentName).forEach(function(element) {
      component.$el.querySelectorAll('slot').forEach(function(slot) {
        slot.innerHTML = element.innerHTML;
      });
      element.innerHTML = component.$el.outerHTML;
    });
  });
};

// 使用示例
var HelloComponent = {
  data: function() {
    return {
      name: 'John'
    };
  },
  template: `
    <div>
      <h1>{
   
   { name }}</h1>
      <slot></slot>
    </div>
  `
};

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello, Vue!'
  },
  components: {
    HelloComponent
  },
  template: `
    <HelloComponent>
      <p>{
   
   { message }}</p>
    </HelloComponent>
  `
});

이 예제에서는 ,  및 를  포함하는  옵션 개체를 Vue 사용하는 생성자를  정의합니다  .datatemplatecomponents

이 방법 에서는   데이터의 양방향 바인딩을 실현하기 위해 데이터 객체의 속성을 Vue 인스턴스에 프록시하는 데 _proxyData 사용합니다  .Object.defineProperty

이 메서드 에서는  _compileTemplate 먼저 구성 개체에서 템플릿 문자열을 가져오고 정규식을 사용하여  { { expression }} 부품을 일치시킵니다. 그런 다음 함수를 사용하여  eval 식을 동적으로 평가하고 값을 다시 템플릿 문자열로 대체합니다. 참고: 여기에서는  이 예제에 추가된 메서드 때문에  eval 이전  문이 아닌 이전  with 문이 뒤따릅니다   . 다음으로 구성 개체의 속성에 따라   해당 DOM 요소를 가져옵니다  .DOM 요소가 존재하지 않으면  대신 요소를 생성한 다음 컴파일된 템플릿 문자열을   요소의 속성에 할당합니다.  그런 다음 Vue 인스턴스에 대한 속성을  설정합니다  .참고: 요소를 대신 사용하는 경우  해당 요소를 제외   해야 합니다   .selfself._data_proxyDataeldivinnerHTML$eldivchildNodes[0]div

방법 에서  _proxyComponents 우리는 먼저 구성 개체에서 구성 요소 선언을 얻은 다음 모든 구성 요소를 순회하고 구성 요소 이름에 따라 구성 요소 개체를 얻고 개체의 인스턴스를 만들고 인스턴스의 속성을 사용하여 모든 슬롯을 순회하고 원본을 슬롯의 내용으로 설정한 다음 구성 요소의 내용   을   인스턴스  Vue 요소   로   재설정   합니다   .$elslotinnerHTMLinnerHTML$elouterHTML

마지막으로 먼저 개체를 정의  HelloComponent 하고 구성 요소의 템플릿에 슬롯을 추가합니다  slot . 그런 다음 다른  Vue 인스턴스를 만들고 구성 개체의 템플릿에 구성 요소를 도입  HelloComponent 하고 구성 요소의 슬롯 콘텐츠를 추가합니다. 이러한 방식으로 Vue.js와 유사한 이벤트를 던지고 받는 기능을 시뮬레이션합니다.

마찬가지로 위의 코드는 ChatGPT에서 완전히 생성되지 않습니다. 원래 생성된 코드에는  VueComponent 생성자도 생성되지만 슬롯 내용의 대체는 구현되지 않았으며, 사용예제 외에는 슬롯 관련 코드가 없고 사용  components 예제 코드에 있는 객체까지 제가 추가한 것입니다.


200줄의 코드로 간소화된 Vue 프레임워크 구현

이전에 Vue의 수명 주기, 템플릿 구문, 명령, 양방향 바인딩, 데이터 모니터링, 계산된 속성, 이벤트 처리, 메서드, 구성 요소 및 슬롯을 시뮬레이션했습니다. 이제 이러한 시뮬레이션 기능을 결합하고 Vue 프레임워크의 간단한 버전을 빌드할 차례입니다. 다음은 쉬운 조롱을 위한 사용 예제 코드입니다.

var HelloComponent = {
  emits: ['greet'],
  data: function() {
    return {
      firstName: 'John',
      lastName: 'Doe'
    };
  },
  computed: {
    fullName: function() {
      return this.firstName + ' ' + this.lastName;
    }
  },
  updated: function() {
    this.$emit('greet', this.firstName);
  },
  template: `
    <div>
      <h1>{
   
   { fullName }}</h1>
      <slot></slot>
    </div>
  `
};

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello, Vue!',
    inputValue: 'ChatGPT'
  },
  watch: {
    message: function(newValue, oldValue) {
      console.log('Message changed:', oldValue, ' -> ', newValue);
    },
    inputValue: function(newValue, oldValue) {
      console.log('InputValue changed:', oldValue, ' -> ', newValue);
    }
  },
  methods: {
    greetMessage: function(message) {
      this.$emit('greet', message);
    },
    updateMessage: function(newMessage) {
      this.message = newMessage;
    }
  },
  components: {
    HelloComponent
  },
  beforeCreate: function() {
    console.log('beforeCreate hook');
  },
  created: function() {
    console.log('created hook');
  },
  beforeMount: function() {
    console.log('beforeMount hook');
  },
  mounted: function() {
    console.log('mounted hook');
  },
  beforeUpdate: function() {
    console.log('beforeUpdate hook');
  },
  updated: function() {
    console.log('updated hook');
  },
  template: `
    <div>
      <HelloComponent v-on:greet="greetMessage">
        <p>{
   
   { message }}</p>
      </HelloComponent>
      <input v-model="inputValue" type="text">
      <p v-text="inputValue"></p>
    </div>
  `
});

app.$on('greet', function(message) {
  console.log('Greet:', message);
});

app.inputValue = 'OpenAI'
app.HelloComponent.firstName = 'Tom';
app.updateMessage('Hello, World!');

app.HelloComponent.firstName 이 코드는 응용 프로그램이 구성 요소 이름을 통해 하위 구성 요소의 인스턴스를 얻을 수 있고 v-on:greet 하위 구성 요소의 이벤트를 수신할 수 있는 등 이전 기능을 기반으로 하는 새 기능을 추가합니다  . 특히 이벤트와 관련하여  greet 발생하는 작업 순서는 다음과 같습니다.

  •  이벤트는  구성  HelloComponent 요소의 수명 주기  updated 동안 발생하며  이벤트의 매개변수는  속성입니다.greetfirstName
  • 앱 애플리케이션의 템플릿에서  <HelloComponent v-on:greet="greetMessage"> 수신  HelloComponent 구성 요소  의 이벤트가 선언되고 greet 이벤트가 앱 애플리케이션의 구성 개체에서 메서드를 트리거합니다  greetMessage .
  • 앱 애플리케이션의 메서드에서   이벤트가  greetMessage 다시 발생  하고 애플리케이션의 인스턴스가  이벤트를   수신하여   값을 출력합니다.greetapp.$on('greet', ...)greetfirstName

위의 코드를 실행한 결과 출력 HTML 페이지 코드는 다음과 같습니다.

<div id="app">
  <div>
    <hellocomponent v-on:greet="greetMessage">
      <div>
        <h1>Tom Doe</h1>
        <slot>
          <p>Hello, World!</p>
        </slot>
      </div>
    </hellocomponent>
    <input v-model="inputValue" type="text" />
    <p v-text="inputValue">OpenAI</p>
  </div>
</div>

콘솔 출력 결과는 다음과 같습니다. 또한 콘솔 입력 및 기타 방식에서  app.inputValue = 123 데이터 양방향 바인딩의 효과를 관찰 할 수 있습니다.

beforeCreate hook
created hook
beforeMount hook
mounted hook
InputValue changed: ChatGPT  ->  OpenAI
beforeUpdate hook
updated hook
Greet: Tom
Message changed: Hello, Vue!  ->  Hello, World!
beforeUpdate hook
updated hook

다음은 200줄의 코드만 필요한 Vue 프레임워크의 단순화된 버전인 이 기사의 핵심입니다.

function EventBus() {
  this._events = {};
}

EventBus.prototype.on = function(eventName, callback) {
  if (!this._events[eventName]) {
    this._events[eventName] = [];
  }
  this._events[eventName].push(callback);
};

EventBus.prototype.emit = function(eventName, payload) {
  if (this._events[eventName]) {
    this._events[eventName].forEach(function(callback) {
      callback(payload);
    });
  }
};

function Vue(options) {
  this.$options = options;

  if (typeof options.beforeCreate === 'function') {
    options.beforeCreate.call(this);
  }

  this._data = typeof options.data === 'function' ? options.data() : options.data;
  this._eventBus = new EventBus();
  this._proxyData();
  this._proxyMethods();
  this._createComputed();
  this._createWatchers();

  if (typeof options.created === 'function') {
    options.created.call(this);
  }

  this.$mount();
}

Vue.prototype.$render = function() {
  if (typeof this.$options.render === 'function' && this.$options.el) {
    this.$el = document.querySelector(this.$options.el);
    this.$el.innerHTML = this.$options.render.call(this);
  } else {
    this._compileTemplate();
    this._proxyComponents();
  }
};

Vue.prototype.$mount = function() {
  if (typeof this.$options.beforeMount === 'function') {
    this.$options.beforeMount.call(this);
  }

  this.$render();

  if (typeof this.$options.mounted === 'function') {
    this.$options.mounted.call(this);
  }
};

Vue.prototype._proxyData = function() {
  var self = this;
  Object.keys(this._data).forEach(function(key) {
    Object.defineProperty(self, key, {
      get: function() {
        return self._data[key];
      },
      set: function(newValue) {
        self._data[key] = newValue;
        if (typeof self.$options.beforeUpdate === 'function') {
          self.$options.beforeUpdate.call(self);
        }

        self.$render();

        if (typeof self.$options.updated === 'function') {
          self.$options.updated.call(self);
        }
      }
    });
  });
};

Vue.prototype._createComputed = function() {
  var self = this;
  var computed = this.$options.computed || {};

  Object.keys(computed).forEach(function(key) {
    Object.defineProperty(self, key, {
      get: function() {
        return computed[key].call(self);
      }
    });
  });
};

Vue.prototype._createWatchers = function() {
  var self = this;
  var watch = this.$options.watch || {};

  Object.keys(watch).forEach(function(key) {
    var callback = watch[key]
    var value = self._data[key];

    Object.defineProperty(self._data, key, {
      get: function() {
        return value;
      },
      set: function(newValue) {
        var oldValue = value
        value = newValue;
        callback.call(self, newValue, oldValue);
      }
    });
  });
};

Vue.prototype._proxyMethods = function() {
  var self = this;
  var methods = this.$options.methods || {};
  Object.keys(methods).forEach(function(key) {
    self[key] = methods[key].bind(self);
  });
};

Vue.prototype.$emit = function(eventName, payload) {
  this._eventBus.emit(eventName, payload);
};

Vue.prototype.$on = function(eventName, callback) {
  this._eventBus.on(eventName, callback);
};

Vue.prototype._compileTemplate = function() {
  var self = this;
  var el = this.$options.el
  var template = this.$options.template || '';

  var evalExpression = function(expression) {
    with (self) return eval(expression);
  }

  var compiledTemplate = template.replace(/\{\{(.*?)\}\}/g, function(match, expression) {
    var value = evalExpression(expression);
    return value !== undefined ? value : '';
  });

  var element = el ? document.querySelector(el) : document.createElement('div');
  element.innerHTML = compiledTemplate.trim();
  this.$el = el ? element : element.childNodes[0];
  this._handleDirective()
};

Vue.prototype._handleDirective = function() {
  var self = this;

  this.$el.querySelectorAll('[v-model]').forEach(function(element) {
    var value = element.getAttribute('v-model');
    element.value = self._data[value];
    element.addEventListener('input', function(event) {
      self._data[value] = event.target.value;
      self.$emit(`update:${value}`, event.target.value);
    });
  });

  this.$el.querySelectorAll('[v-text]').forEach(function(element) {
    var value = element.getAttribute('v-text');
    element.textContent = self._data[value];
    self.$on(`update:${value}`, function(newValue) {
      element.textContent = newValue;
    });
  });
};

Vue.prototype._proxyComponents = function() {
  var self = this;
  var components = this.$options.components || {};

  Object.keys(components).forEach(function(componentName) {
    var component = self[componentName] || new Vue(components[componentName]);
    var isNewComponent = typeof self[componentName] === 'undefined';
    self[componentName] = component;

    self.$el.querySelectorAll(componentName).forEach(function(element) {
      component.$el.querySelectorAll('slot').forEach(function(slot) {
        slot.innerHTML = element.innerHTML;
      });
      element.innerHTML = component.$el.outerHTML;

      isNewComponent && component.$options?.emits.forEach(function(event) {
        var method = element.getAttribute('v-on:' + event);
        if (typeof self[method] === 'function') {
          component.$on(event, self[method]);
        }
      });
    });
  });
};

Vue 생성자에서 여러 가지 작업을 수행합니다. 수명 주기 후크 함수 처리,  인스턴스  EventBus 생성  _proxyData , , _proxyMethods, _createComputed, _createWatchers 메서드를 사용하여 속성, 메서드, 계산된 속성 및 Vue 인스턴스에 대한 데이터 개체의 리스너를 프록시하거나 바인딩합니다.

그런 다음  $mount 메서드를 호출하여 구성 요소를 마운트하고 수명 주기 후크 함수를 트리거한 다음  $render 메서드를 실행합니다. 메서드 에서  $render 사용자 정의 렌더링 함수를 실행하거나 , 메서드를 사용하여  _compileTemplate 템플릿 _proxyComponents 을 컴파일하고 하위 구성 요소를 해결합니다.

_proxyData 메서드  에서   인스턴스  Object.defineProperty 에 위임할 데이터 개체의 속성을  사용하고 속성의  메서드  에서 트리거  및  후크  를  사용  합니다. 즉, 데이터 개체의 속성이 변경되는 한 보기 업데이트가 트리거됩니다.VuesetbeforeUpdate$renderupdated

메서드 에서는  객체를 _createComputed 순회하여  computed 계산된 각 속성에 대한 메서드를 정의하여  get일반 속성으로 사용할 수 있도록 합니다.

_createWatchers 메소드  에서  우리는 객체를 순회하고 watch 각 속성에 대한  객체의 속성 변경에 Object.defineProperty 모니터  객체를 사용 _data 하고 변경이 발생할 때 콜백 함수를 트리거합니다. 참고:  set 방법  에서 oldValue 이전과 비교하여 새 매개변수를 추가했습니다.

메서드 에서  _proxyMethods 구성 개체의 메서드를 Vue 인스턴스에 바인딩하여 이러한 메서드를 인스턴스에서 직접 액세스하고 호출할 수 있습니다.

프로토타입 에서   및  메서드를 Vue 정의합니다   .  이 메소드는 이벤트를 발생시키는 데 사용되며 이벤트 이름과 선택적 데이터 페이로드라는 두 개의 매개변수를 수신합니다.  이 메서드는 이벤트를 수신하는 데 사용되며 이벤트 이름과 콜백 함수라는 두 가지 매개변수를 받습니다.$emit$on$emit$on

이 메서드 에서는  _compileTemplate 먼저 구성 개체에서 템플릿 문자열을 가져오고 정규식을 사용하여  { { expression }} 부품을 일치시킵니다. 그런 다음 함수를 사용하여  eval 식을 동적으로 평가하고 값을 다시 템플릿 문자열로 대체합니다. 다음으로 구성 개체의 속성에 따라  el 해당 DOM 요소를 가져옵니다  .DOM 요소가 존재하지 않으면 div 대신 요소를 생성한 다음 컴파일된 템플릿 문자열을  innerHTML 요소의 속성에 할당합니다. 그런 다음  $el Vue 인스턴스에 속성을 설정하고  _handleDirective 메서드 핸들러를 호출합니다. 참고: 요소를 대신 사용하는 경우   해당 요소를 제외  div 해야 합니다   .childNodes[0]div

_handleDirective 메서드  에서   메서드를 통해 특성이 있는 querySelectorAll 모든 요소를 ​​가져오고  각 요소를 반복합니다. v-model순회하는 동안 지시문을 구문 분석하고  model 요소 값을 해당 데이터 속성 값으로 설정하고  input 이벤트 리스너를 추가합니다. 참고:  addEventListener 이 방법에서는 이전 방법과 비교하여  이벤트를 $emit 트리거하는 작업을  추가하여  완전한 양방향 데이터 바인딩을 update:inputValue 달성했습니다  .inputValue

다음으로   메소드를 통해 속성이 있는 querySelectorAll 모든 요소를 ​​가져오고  각 요소를 반복합니다. v-text순회하는 동안 지시문을 구문 분석  text 하고 요소의 텍스트 콘텐츠를 해당 데이터 속성 값으로 설정합니다. $on 참고: 이전 작업과 비교하여 이벤트를 수신  update:inputValue 하고 텍스트 콘텐츠가  inputValue 의 값으로 변경되도록 하는 새로운 작업을 추가했습니다  .

메서드 에서  _proxyComponents 먼저 구성 개체에서 구성 요소 선언을 얻은 다음 모든 구성 요소를 순회하고 구성 요소 이름에 따라 구성 요소 개체를 얻고  Vue 개체의 인스턴스를 만듭니다. 참고: 이전과 비교하여 개체를 인스턴스에 저장하고 인스턴스에서 생성된 개체를 먼저 가져옵니다. 그런 다음   인스턴스의 속성을 통해  $el 모든 슬롯을 순회  하고 원래 항목을  슬롯의 콘텐츠로 설정하고 구성 요소의 콘텐츠를   인스턴스   요소  로 재설정합니다  .slotinnerHTMLinnerHTML$elouterHTML

v-on 마지막으로 컴포넌트 수신 이벤트 기능 도 추가했습니다  . 먼저 컴포넌트 구성 객체  emits 의 배열에서 컴포넌트가 던진 모든 이벤트 이름을 가져온  다음 배열을 순회하여 앱 애플리케이션이 이벤트를 수신했는지 여부를 확인 self[method] 하고 해당 리스너 함수가 앱 애플리케이션에서 발견되면  $on 메소드를 통해 리스너 함수를 컴포넌트에 바인딩합니다. 참고: 구성 요소 업데이트는 여러 메서드를 트리거하므로  동일한 수신기 함수에 대한 메서드 바인딩  이 반복되지 않도록 새로 생성된 구성 요소인지  _proxyComponents 확인해야 합니다   .isNewComponent$on


요약하다

Vue의 원리를 시뮬레이션하기 위한 위의 샘플 코드는 모두 현재 우리가 일반적으로 사용하는 Composition API와 다른 Vue의 Option API 방식으로 작성되었습니다. 이것은 내가 사용하는 ChatGPT 버전이 2021년 이전에만 정보를 얻을 수 있다는 사실과 관련이 있을 수 있지만 이것이 Vue 사용법을 배우고 Vue의 원리를 이해하는 데 사용하는 것을 막지는 않습니다.

이 기사에서 다루는 내용은 비교적 기초적이며 Vue에는 많은 고급 기능과 사용법이 있습니다.AI를 사용하여 학습을 안내할 수 있습니다. 물론 학습하는 과정에서 AI의 답이 완벽하게 맞는 것은 아니라는 점에 항상 주의를 기울여야 하고, 연습을 통해 하나씩 알아내야 한다. Vue의 실제 개발 과정에서 우리는 AI를 사용하여 문제를 찾고 분석할 수 있습니다.결국 지칠 줄 모르고 성질이 좋고 보기 드문 좋은 선생님입니다.

이 기사의 모든 소스 코드와 샘플 프로젝트는  OpenTiny 사이트에 있습니다.  GitHub - opentiny/ai-vue를 방문하십시오.

추천

출처blog.csdn.net/OpenTiny/article/details/131142949