JavaScript で MVC_javascript テクニックを実装するためのコードはわずか 30 行です
2009 年頃から、MVC はフロントエンドの分野で徐々に頭角を現し、2015 年の React Native の立ち上げでついに大爆発を迎えました: AngularJS、EmberJS、Backbone、ReactJS、RiotJS、VueJS... ..一連の名前が出現し、派手に変化してきましたが、その中には徐々に人々の目から消えていくものもあれば、現在も急速に成長しているものもあれば、すでに特定の生態環境の中で独自の役割を果たしているものもあります。しかし、何があっても、MVC はフロントエンド エンジニアの考え方や仕事のやり方に大きな影響を与えてきましたし、これからも影響し続けるでしょう。
MVC を説明する多くの例は、Backbone のコレクションや AngularJS のモデルなど、特定のフレームワークの特定の概念から始まります。これは確かに良いアプローチです。しかし、フレームワークがクラス ライブラリ (jQuery) やツール セット (アンダースコア) ではなくフレームワークである理由は、その背後に多くの優れた設計コンセプトとベスト プラクティスがあるためです。これらの設計エッセンスは相互に補完し、連動しており、が不可欠ですが、複雑なフレームワークを通して短期間で特定のデザインパターンの本質を理解するのは簡単ではありません。
これがこのエッセイの原点です。誰もが概念を理解できるように作成されたプロトタイプ コードは、できる限り単純である必要があります。誰もが概念を理解できる程度に単純である必要があります。
1. MVC の基礎はオブザーバー パターンであり、これがモデルとビュー間の同期を実現するための鍵となります
簡単にするために、各モデル インスタンスにはプリミティブ値が 1 つだけ含まれています。
function Model(value) { this._value = typeof value === 'undefined' ? '' : value; this._listeners = []; } Model.prototype.set = function (value) { var self = this; self._value = value; // model中的值改变时,应通知注册过的回调函数 // 按照Javascript事件处理的一般机制,我们异步地调用回调函数 // 如果觉得setTimeout影响性能,也可以采用requestAnimationFrame setTimeout(function () { self._listeners.forEach(function (listener) { listener.call(self, value); }); }); }; Model.prototype.watch = function (listener) { // 注册监听的回调函数 this._listeners.push(listener); };
// html代码: <div id="div1"></div> // 逻辑代码: (function () { var model = new Model(); var div1 = document.getElementById('div1'); model.watch(function (value) { div1.innerHTML = value; }); model.set('hello, this is a div'); })();
オブザーバー パターンの助けを借りて、モデルの set メソッドがその値を変更するために呼び出されるとき、テンプレートも同期的に更新されることがわかりました。しかし、この実装は、変更を手動で監視する必要があるため、非常に扱いにくいです。モデル値を (watch メソッドを介して) 取得し、コールバック関数に渡します。ビュー (1 つ以上の dom ノード) をモデルにバインドすることを簡単にする方法はありますか?
2. binding メソッドを実装し、モデルとビューをバインドします
Model.prototype.bind = function (node) { // 将watch的逻辑和通用的回调函数放到这里 this.watch(function (value) { node.innerHTML = value; }); };
// html代码: <div id="div1"></div> <div id="div2"></div> // 逻辑代码: (function () { var model = new Model(); model.bind(document.getElementById('div1')); model.bind(document.getElementById('div2')); model.set('this is a div'); })();
シンプルなカプセル化により、複数のビューをバインドする必要がある場合でも、ビューとモデル間のバインディングが簡単に実装できます。バインドは Function クラスのプロトタイプのネイティブ メソッドですが、作者はバインドという言葉を非常に気に入っているので、ここでは単にネイティブ メソッドについて説明します。 。さらに言えば、バインディングの複雑さは軽減されましたが、このステップでは依然としてバインディング ロジックをビジネス コードから完全に分離することが可能でしょうか。
3. ロジック コードからバインディングを分離するコントローラーを実装します
注意深い人は、MVC について話しているにもかかわらず、上の記事には Model クラスしか登場していないことに気づいたかもしれません。結局のところ、HTML は既成の View であることは理解できます。 、この記事でも最初から最後まで言及していますが、HTML を View として使用するだけでは、View クラスは JavaScript コードに表示されません)、では、なぜコントローラー クラスが表示されないのでしょうか。心配しないでください。実際、いわゆる「ロジック コード」は、フレームワーク ロジック (この記事のプロトタイプをフレームワークと呼ぶことにします) とビジネス ロジックの間の高度な結合を持つコード セグメントです。これを分解してみましょう。
バインディング ロジックをフレームワークに任せたい場合は、バインディングを完了する方法をフレームワークに指示する必要があります。 JS でアノテーションを完了するのは難しいため、ビューでこのマークアップ層を実行できます。HTML のタグ属性を使用するのが簡単で効果的な方法です。
function Controller(callback) { var models = {}; // 找到所有有bind属性的元素 var views = document.querySelectorAll('[bind]'); // 将views处理为普通数组 views = Array.prototype.slice.call(views, 0); views.forEach(function (view) { var modelName = view.getAttribute('bind'); // 取出或新建该元素所绑定的model models[modelName] = models[modelName] || new Model(); // 完成该元素和指定model的绑定 models[modelName].bind(view); }); // 调用controller的具体逻辑,将models传入,方便业务处理 callback.call(this, models); }
// html: <div id="div1" bind="model1"></div> <div id="div2" bind="model1"></div> // 逻辑代码: new Controller(function (models) { var model1 = models.model1; model1.set('this is a div'); });
そんなに簡単ですか?それはとても簡単です。 MVC の本質は、コントローラー内でビジネス ロジックを完成させ、同時にモデルを変更することで、これらのロジックが上記のコードに反映され、複数のビューと複数のモデルをサポートします。本番プロジェクトには十分ではありませんが、皆様の MVC 学習に少しでもお役に立てれば幸いです。
コメントが削除された整理された「フレームワーク」コード:
function Model(value) { this._value = typeof value === 'undefined' ? '' : value; this._listeners = []; } Model.prototype.set = function (value) { var self = this; self._value = value; setTimeout(function () { self._listeners.forEach(function (listener) { listener.call(self, value); }); }); }; Model.prototype.watch = function (listener) { this._listeners.push(listener); }; Model.prototype.bind = function (node) { this.watch(function (value) { node.innerHTML = value; }); }; function Controller(callback) { var models = {}; var views = Array.prototype.slice.call(document.querySelectorAll('[bind]'), 0); views.forEach(function (view) { var modelName = view.getAttribute('bind'); models[modelName] = models[modelName] || new Model(); models[modelName].bind(view); }); callback.call(this, models); }
後記:
筆者在學習flux和redux的過程中,雖然掌握了工具的使用方法,但只是知其然而不知其所以然,對ReactJS官方文件中一直強調的"Flux eschews MVC in favor of a unidirectional data flow"不甚理解,始終覺得單向資料流和MVC並不衝突,不明白為什麼在ReactJS的文檔中這二者會被對立起來,有他無我,有我無他(eschew,避開)。終於下定決心,回到MVC的定義上重新研究,雖然平日工作里大大咧咧複製粘貼,但是咱們偶爾也得任性一把,咬文嚼字一番,對吧?這樣的方式也的確幫助了我對這句話的理解,這裡可以把自己的思考分享給大家:之所以覺得MVC和flux中的單向資料流相似,可能是因為沒有區分清楚MVC和觀察者模式的關係所造成的-MVC是基於觀察者模式的,flux也是,因此這種相似性的由來是觀察者模式,而不是MVC和flux本身。這樣的理解也在四人組的設計模式原著中得到了印證:"The first and perhaps best-known example of the Observer pattern appears in Smalltalk Model/View/Controller (MVC), the user interface framework in the Smalltalk environment [KP88]. MVC's Model class plays the role of Subject, while View is the base class for observers. "。
如果讀者有興趣在這樣一個原型玩具的基礎上繼續拓展,可以參考下面的一些方向:
- 1. 實作對input類別標籤的雙向綁定
- 2. 實現對controller所控制的scope的精準控制,這裡一個controller就控制了整個dom樹
- 3. 實作view層有關dom node隱藏/顯示、建立/銷毀的邏輯
- 4. 整合virtual dom,增加dom diff的功能,提高渲染效率
- 5. 提供依賴注入功能,實現控制反轉
- 6. 對innerHTML的賦值內容進行安全檢查,防止惡意注入
- 7. 實作model collection的邏輯,這裡每個model只有一個值
- 8. 利用es5中的setter改變set方法的實現,使得model的修改更加簡單
- 9. 在view層中增加對屬性和css的控制
- 10.支援類似AngularJS中雙大括號的語法,只綁定部分html
- ……
一個完善的框架要經過無數的提煉和修改,這裡只是最初最初的第一步,道路還很漫長,希望大家再接再厲。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

はじめに 今日の急速に進化するデジタル世界では、堅牢かつ柔軟で保守可能な WEB アプリケーションを構築することが重要です。 PHPmvc アーキテクチャは、この目標を達成するための理想的なソリューションを提供します。 MVC (Model-View-Controller) は、アプリケーションのさまざまな側面を独立したコンポーネントに分離する、広く使用されている設計パターンです。 MVC アーキテクチャの基礎 MVC アーキテクチャの核となる原則は、関心事の分離です。 モデル: アプリケーションのデータとビジネス ロジックをカプセル化します。ビュー: データの表示とユーザー インタラクションの処理を担当します。コントローラー: モデルとビュー間の対話を調整し、ユーザーのリクエストとビジネス ロジックを管理します。 PHPMVC アーキテクチャ phpMVC アーキテクチャは従来の MVC パターンに従いますが、言語固有の機能も導入しています。以下はPHPMVCです

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

使用法: JavaScript では、insertBefore() メソッドを使用して、DOM ツリーに新しいノードを挿入します。このメソッドには、挿入される新しいノードと参照ノード (つまり、新しいノードが挿入されるノード) の 2 つのパラメータが必要です。
