AI は、200 行のコードで簡略化された Vue フレームワークを書くように教えてくれました

AI は未来の最高の教師です

最近、Vue の基礎に関する学習教材を準備していました。この期間中に、私は気まぐれに考えました。学習コンテンツの作成に人気の ChatGPT を使用できないか? 実際、Vue 自体の習得、特に基本的な使い方は難しくありませんが、Vue をより深くマスターしたい場合は、Vue のソース コードを読んで原理を理解する必要があります。ただし、誰もが Vue のソース コードを読むのに十分な時間と忍耐力を持っているわけではありません。そこで私は 1 時間以上かけて ChatGPT と対話し、Vue の原理を示すサンプル コードを生成するように導きました。このプロセスでは、私は質問者として行動し、ChatGPT に質問に従って必要なコードを生成させます。この結果は私にとって少し驚きでしたが、完全に予想外というわけではありませんでした。現在のAIの急速な発展傾向を考えると、2024年までには多くの職業がAIに置き換わると考えられており、その時点でAIが教師を完全に置き換えることはできませんが、パーソナルティーチングアシスタントツールとなる可能性は十分にあります。私は、未来はAIが人間に取って代わるのではなく、AIの使い方を知らない人にAIの使い方を知っている人が置き換わることだと信じています。次に、このAIティーチングアシスタントのレベルを一緒に見ていきましょう。

この記事では主に以下の内容についてお話します。

  • AI に Vue の入門から上級までの学習概要をリスト化してもらう
  • AI に Vue がどのように機能するかを説明するコード例を提示してもらいます
  • Vue ライフサイクルの原則を学び始めましょう
  • Vue テンプレートの構文とディレクティブの原則を学ぶ
  • Vue データの監視とプロパティの計算の原則を学ぶ
  • Vue イベント処理の原則とメソッドを学ぶ
  • Vueスロット(スロット)の原理を学ぶ
  • 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. Vue コンポーネント
    • 基本的な考え方と部品構成
    • コンポーネントの登録と使用
    • コンポーネントの通信方法 (props、event、vuex)
    • 動的コンポーネントと非同期コンポーネント
    • スロットとスコープ付きスロット
  4. Vueルーティング
    • Vue Router のインストールと構成
    • ルーティングの基本的な使用法 (ナビゲーション、パラメーターの受け渡し)
    • ネストされた名前付きルート
    • ルーティングガードとナビゲーション分析
  5. Vue 状態管理 (Vuex)
    • Vuex の中心となる概念と使用シナリオ
    • Vuex のインストールと構成
    • 状態、突然変異、アクション、ゲッター
    • モジュール性と名前空間
  6. アドバンストビュー
    • カスタムディレクティブ
    • フィルター
    • 混入(Mixin)
    • プラグイン
    • カスタムトランジションとアニメーション
    • サーバーサイドレンダリング (SSR)
  7. Vue と外部ライブラリの統合
    • Axios を使用した HTTP リクエスト
    • Vue を使用してサードパーティ ライブラリ (Chart.js、Google マップなど) と統合します。
    • Vue と Webpack を使用したプロジェクトのビルド
  8. Vue のベスト プラクティスとパフォーマンスの最適化
    • コンポーネントの分割と再利用
    • 計算されたプロパティとリスナーの賢明な使用
    • 不必要なレンダリングを避ける
    • 非同期コンポーネントとコード分割
    • ネットワークリクエストとデータロードを最適化する
  9. Vueテスト
    • 単体テストとエンドツーエンド テストの概念
    • Vue Test Utils を使用した単体テスト
    • Cypress を使用したエンドツーエンドのテスト
  10. Vue プロジェクトの戦闘
    • Vue.js に基づいて完全なアプリケーションを構築する
    • Vue Router と Vuex による状態管理
    • 他のライブラリやツールを統合する
    • アプリケーションのテストと最適化

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

上記の内容は ChatGPT で生成されたものであり、ある程度の普遍性はありますが、この概要に従うつもりはなく、Vue のソースコードを読みながら Vue の使い方を習得していただければ幸いです。たとえば、多くの人は Vue データの双方向バインディングの使用法が非常に簡単だと考えていますが、データの双方向バインディングの実現をシミュレートするのは簡単ではありません。Vue の使用方法を学習するためにその原則を習得する必要がある主な理由は 4 つあります (これらの理由は 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 、該当するタイミングでフック関数を呼び出します。このメソッドでは 、 指定された DOM 要素にテンプレートをレンダリングするメソッドを$mount 呼び出します 。render

_proxyData このメソッド では 、 インスタンス Object.defineProperty に委任されるデータ オブジェクトのプロパティを 使用し、プロパティの メソッド 内でトリガー と フックを使用します。これは、データ オブジェクト の  プロパティが変更される限り、ビューの更新がトリガーされることを意味します。VuesetbeforeUpdaterenderupdated

render メソッド では 、render 構成オブジェクトに関数が定義されているかどうかを判断し、関数を通じてレンダリングされたコンテンツを取得し、それを $el 要素の 属性に割り当てますinnerHTML 。 $el 要素は $mount メソッド内で初期化されます document.querySelector 。

最後に、例の構成オブジェクトを使用して をインスタンス化し Vue 、レンダリングをシミュレートすることでライフ サイクル フック関数をトリガーして、Vue.js と同様の各ライフ サイクルの効果を実現します。

上記のコードの説明も ChatGPT によって生成されたものですが、いくつか説明を追加しただけです。この分野における ChatGPT の能力はプロの家庭教師に劣らないことがわかり、レッスンの準備にかかる時間を大幅に節約できるだけでなく、部分的には私よりも上手に話すことができます。

上記の JavaScript コードは直接実行できません。コードを lifecycle.js ファイルとして保存し、  index.html Web ページを作成してそのファイルを参照します。Web ページのコードは次のとおりです。

<!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 フラグメント自体はテンプレートのコンテンツであり、テンプレート構文と 2 つのディレクティブを使用します。テンプレート構文は 、 ディレクティブは{ { message }}それぞれ v-model と ですv-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 注:このディレクティブには双方向バインディングが実装されていません 。

最後に、 example の config オブジェクトを使用してインスタンスを作成し Vue、テンプレート文字列を渡します。テンプレートの解析と命令の実行をシミュレートすることで、Vue.js と同様のテンプレート構文と命令の効果を実現しました。効果を確認するには、ブラウザでページを開いてください index.html 。

上記のコードは、ChatGPT によって完全に生成されたわけではありません。正常に実行するには、デバッグ プロセス中に 2 つの問題を修正する必要があるためです。

  • 最初の問題は、ChatGPT が eval 関数を直接使用して式を動的に評価したいことです。ChatGPT によって生成されるコードは eval(expression)、 expression 文字列です 。 両側にスペースがあること" message "に注意してください 。 グローバル オブジェクトには属性が定義されておらず、  式の本来の目的は  オブジェクトの 属性値を取得することであるため、 関数 をmessage直接呼び出して 取得した値 はエラーを報告します  。このため、  値が正しく取得できるように、 ステートメント を通じて グローバル オブジェクトを設定する  関数 を追加しました。ただし、  このステートメントを厳密モードで使用することは推奨されていないため、最適解ではありません。興味のある学生は最適解を学習できます。evalmessagemessage{ { message }}this._datamessageevalExpressionwiththis._datathis._data.messagewith

  • querySelectorAll('[v-]') 2つ目は、ChatGPTが同時取得 v-model と 命令の内容を利用したいのに v-text 、実際のデバッグ処理中に取得できないという問題です。そこで、これを 2 つのステートメントに分解し、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 オブジェクトには、 on イベントをリッスンするメソッドと emit イベントを起動するメソッドがあります。

Vue コンストラクター で EventBus インスタンスを作成し、それをプロパティに割り当てます _eventBus 。

このメソッドでは 、 データの双方向バインディングを実現するために、データ オブジェクトのプロパティを Vue インスタンスにプロキシするために_proxyData 使用します 。Object.defineProperty

このメソッドでは _proxyMethods 、構成オブジェクト内のメソッドを Vue インスタンスにバインドし、これらのメソッドに直接アクセスしてインスタンス内で呼び出すことができるようにします。

Vue プロトタイプ では 、$emit と $on メソッドを定義します。 $emit このメソッドはイベントをスローするために使用され、イベント名とオプションのデータ ペイロードという 2 つのパラメーターを受け取ります。 $on このメソッドはイベントをリッスンするために使用され、イベント名とコールバック関数という 2 つのパラメーターを受け取ります。

最後に、インスタンスを作成し Vue 、既存の Vue 構成オブジェクト のメソッドが メソッド トリガー  イベントをgreet 使用して コールバック関数をトリガーし、メッセージを出力します。次に、メソッドを使用してインスタンス内の イベント をリッスンし  、メッセージを出力するコールバック関数を定義します。このようにして、Vue.js と同様にイベントを送受信する機能をシミュレートします。$emitgreet$ongreet

前と同様、上記のコードは ChatGPT によって正確に生成されたものではありません。元の生成されたコードには、イベントのスローとイベントの受信の模擬実装はありません。ChatGPT によって生成されたコードという新しいプロンプトを表示し EventBus 、2 つのコードをマージして上記のサンプル コードを取得しました。


AIを使ってVueスロット(スロット)の原理を学習する

最後に、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 2 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 にスローされ greet 、イベントのパラメーターは firstName プロパティです。
  • アプリ アプリケーションのテンプレートでは、 <HelloComponent v-on:greet="greetMessage"> リッスン HelloComponent コンポーネント のイベントが宣言されておりgreet 、そのイベントはアプリ アプリケーションの構成オブジェクト内のメソッドをトリガーします greetMessage 。
  • アプリ application のメソッドでは  、イベントが 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 このメソッドはイベントをスローするために使用され、イベント名とオプションのデータ ペイロードという 2 つのパラメーターを受け取ります。 $on このメソッドはイベントをリッスンするために使用され、イベント名とコールバック関数という 2 つのパラメーターを受け取ります。

このメソッドでは _compileTemplate 、まず構成オブジェクト内のテンプレート文字列を取得し、正規表現を使用して { { expression }} その部分を照合します。次に、 eval 関数を使用して式を動的に評価し、その値をテンプレート文字列に置き換えます。次に、構成オブジェクトのプロパティに従って、 el 対応する DOM 要素を取得します 。DOM 要素が存在しない場合は、div 代わりに要素を作成し、コンパイルされたテンプレート文字列を innerHTML 要素のプロパティに割り当てます。次に、  $el Vue インスタンスにプロパティを設定し、 _handleDirective メソッド ハンドラーを呼び出します。注: div 代わりに要素を使用する場合は、 childNodes[0] その要素を除外する 必要がありますdiv 。

_handleDirective このメソッド では 、 メソッドを通じて属性を持つquerySelectorAll すべての要素を取得し 、各要素を反復処理します。 トラバーサル中に、ディレクティブを v-model解析し 、要素の値を対応するデータ属性値に設定し、 イベント リスナーを追加します。注: このメソッドでは 、以前のメソッドと比較して、 完全な双方向データ バインディング を実現するために、イベントを  トリガーするアクションを  追加しました 。modelinputaddEventListener$emitupdate:inputValueinputValue

次に、  メソッドを通じて属性を持つquerySelectorAll すべての要素を取得し 、各要素を反復処理します。v-textトラバーサル中に、 text ディレクティブを解析し、要素のテキスト コンテンツを対応するデータ属性値に設定します。$on 注: 以前のアクションと比較して、イベントをリッスンし update:inputValue 、テキストの内容を inputValue の値に応じて変更する新しいアクションを追加しました 。

このメソッドでは _proxyComponents 、まず構成オブジェクト内のコンポーネント宣言を取得し、次にすべてのコンポーネントを走査し、コンポーネント名に従ってコンポーネント オブジェクトを取得し、 Vue オブジェクトのインスタンスを作成します。注: 以前と比較して、オブジェクトをインスタンスに保存し、最初に作成されたオブジェクトをインスタンスから取得します。次に、  インスタンスのプロパティを通じて $el すべてのスロットを調べ 、元のスロットを スロットのコンテンツとして設定し、コンポーネントのコンテンツを  インスタンス  要素 としてリセットします 。slotinnerHTMLinnerHTML$elouterHTML

最後に、 v-on コンポーネントリスニングイベント機能も追加しました。まず、コンポーネント構成オブジェクト emits の配列からコンポーネントによってスローされたすべてのイベント名を取得し 、配列を走査してアプリ アプリケーションがイベントをリッスンしたかどうかを確認します。self[method] 対応するリスナー関数がアプリ アプリケーションから見つかった場合、リスナー $on 関数はメソッドを通じてコン​​ポーネントにバインドされます。注: コンポーネントの更新は複数のメソッドをトリガーするため 、 同じリスナー関数に 繰り返しメソッドがバインドされるのを防ぐために、それが新しく作成されたコンポーネントであるかどうかを _proxyComponents 判断する必要があります 。isNewComponent$on


要約する

Vue の原理をシミュレーションするための上記のサンプル コードはすべて Vue のオプション API の方法で書かれており、私たちが一般的に使用している現在のコンポジション API とは異なります。これは、私が使用している ChatGPT バージョンが 2021 年以前の情報しか取得できないという事実に関連している可能性がありますが、Vue の使用方法を学習し、Vue の原理を理解するためにそれを使用することを妨げるものではありません。

この記事で取り上げる内容は比較的基本的なものですが、Vue には高度な機能や使い方も多数あり、AI を使用して学習をガイドすることもできます。もちろん学習の過程では、AIの答えが完全に正しいわけではないことに常に注意し、実践を通じてそれを一つ一つ見つけていく必要があります。Vue の実際の開発プロセスでも、AI を使用して問題点を特定して分析することができます。

この記事のすべてのソース コードとサンプル プロジェクトは OpenTiny サイトにあります。GitHub  - opentiny/ai-vueにアクセスしてください。

おすすめ

転載: blog.csdn.net/OpenTiny/article/details/131142949