検索
ホームページウェブフロントエンドVue.jsVue のレスポンシブ実装の原理について説明する記事

Vue のレスポンシブ実装の原理について説明する記事

#vue は、多くの便利な機能が組み込まれた使いやすいフレームワークで、最も特徴的な機能は下部に隠されたレスポンシブ システムです。コンポーネントの状態はすべて、応答性の高い JavaScript オブジェクトです。それらを変更するとビューが更新され、状態管理がより簡単かつ直感的になります。では、Vue 応答システムはどのように実装されているのでしょうか?この記事も Vue のソースコードを読んだ上での理解と模倣実装をベースにしていますので、著者の考えに従って Vue を浅いところから深いところまで探っていきましょう! [関連する推奨事項: vuejs ビデオ チュートリアル ]

この記事の Vue ソース コード バージョン: 2.6.14. 理解を容易にするために、コードは簡略化されています。

Vue がデータ応答性を実装する方法

通常の JavaScript オブジェクトをデータ オプションとして Vue インスタンスに渡すと、Vue はオブジェクトのすべてのプロパティを走査します。そして、Object.defineProperty を使用してこれらすべてのプロパティをゲッター/セッターに変換し、ゲッター/セッターを実行します。

Vue の応答システムを一文で要約すると、次のようになります。 Observer モード Object.defineProperty が getter/setter をインターセプト

MDN ObjdefineProperty

#オブザーバー パターン

Object.defineProperty とは何ですか?

Object.defineProperty() メソッドは、オブジェクトの新しいプロパティを直接定義するか、オブジェクトの既存のプロパティを変更します。このオブジェクトを返します。

簡単に言えば、このように定義されたプロパティは、

obj.xxx の実行時に get をトリガーし、obj.xxx = xxx の実行時に set をトリガーします。応答性の鍵となります。

Object.defineProperty は、シム化できない (ポリフィルを介して実装できない) ES5 の機能です。そのため、Vue は IE8 以前のブラウザをサポートしません。

レスポンシブ システムの基本的な実装

次に、

Object.defineProperty に基づいて簡単なシステムを実装しましょう。 「前菜」としてのレスポンシブ更新システム

let data = {};
// 使用一个中间变量保存 value
let value = "hello";
// 用一个集合保存数据的响应更新函数
let fnSet = new Set();
// 在 data 上定义 text 属性
Object.defineProperty(data, "text", {
  enumerable: true,
  configurable: true,
  set(newValue) {
    value = newValue;
    // 数据变化
    fnSet.forEach((fn) => fn());
  },
  get() {
    fnSet.add(fn);
    return value;
  },
});

// 将 data.text 渲染到页面上
function fn() {
  document.body.innerText = data.text;
}
// 执行函数,触发读取 get
fn();

// 一秒后改变数据,触发 set 更新
setTimeout(() => {
  data.text = "world";
}, 1000);
次に、このコードをブラウザで実行すると、望ましい効果が得られます

上記のコードを通じて、あなたはレスポンシブに興味があると思います。システムがどのように機能するかをある程度理解していること。この「前菜」を理解しやすくするために、この単純なリアクティブ システムにはまだ多くの欠点があります。例: データと応答の更新関数はハード コーディングを通じて強く結合されており、1 対 1 の状況のみを実現し、モジュール式ではありません。十分です。お待​​ちください...それでは、次は 1 つずつ完成させていきましょう。

完全な応答システムを設計する

完全な応答システムを設計するには、まず前提条件となる知識、つまりオブザーバー パターンとは何かを理解する必要があります。

オブザーバー パターンとは何ですか?

これは、オブジェクト イベントの発生時にオブジェクトを「監視」する他の複数のオブジェクトに通知できるサブスクリプション メカニズムを定義できる動作設計パターンです。

注目に値するステータスを持つオブジェクトは通常、

ターゲットと呼ばれます。自身のステータスが変化したときに他のオブジェクトに通知する必要があるため、パブリッシャーとも呼ばれます。 ## #。パブリッシャーの状態の変化を追跡したい他のすべてのオブジェクトは、subscribers と呼ばれます。さらに、パブリッシャーはインターフェースを介してのみすべてのサブスクライバーと直接対話し、すべてのサブスクライバーが 同じインターフェースを持っている必要があります

Vue のレスポンシブ実装の原理について説明する記事たとえば?:

あなた (つまり、アプリケーションの購読者) は、特定の書店の週刊誌に興味があり、上司 (つまり、アプリケーション ) の発行者は電話番号を残して、新しい週刊誌が入手可能になり次第、上司に電話するよう依頼しました。この週刊誌に興味を持った他の人も、上司に電話番号を残しました。新しい週刊誌が届くと、上司は読者にそれを受け取るように一人ひとりに電話をかけます。

リーダーが誤って電話番号の代わりに QQ 番号を残した場合、古いバージョンでは電話をかけることができず、リーダーは通知を受信できません。これは上で述べたとおりであり、同じインターフェイスを持つ必要があります。

オブザーバー パターンを理解した後、応答性の高いシステムの設計を開始しました。

抽象オブザーバー (サブスクライバー) クラス Watcher

在上面的例子中,数据和响应更新函数是通过硬编码强耦合在一起的。而实际开发过程中,更新函数不一定叫fn,更有可能是一个匿名函数。所以我们需要抽像一个观察者(订阅者)类Watcher来保存并执行更新函数,同时向外提供一个update更新接口。

// Watcher 观察者可能有 n 个,我们为了区分它们,保证唯一性,增加一个 uid
let watcherId = 0;
// 当前活跃的 Watcher
let activeWatcher = null;

class Watcher {
  constructor(cb) {
    this.uid = watcherId++;
    // 更新函数
    this.cb = cb;
    // 保存 watcher 订阅的所有数据
    this.deps = [];
    // 初始化时执行更新函数
    this.get();
  }
  // 求值函数
  get() {
    // 调用更新函数时,将 activeWatcher 指向当前 watcher
    activeWatcher = this;
    this.cb();
    // 调用完重置
    activeWatcher = null;
  }
  // 数据更新时,调用该函数重新求值
  update() {
    this.get();
  }
}

抽象被观察者(发布者)类Dep

我们再想一想,实际开发过程中,data 中肯定不止一个数据,而且每个数据,都有不同的订阅者,所以说我们还需要抽象一个被观察者(发布者)Dep类来保存数据对应的观察者(Watcher),以及数据变化时通知观察者更新。

class Dep {
  constructor() {
    // 保存所有该依赖项的订阅者
    this.subs = [];
  }
  addSubs() {
    // 将 activeWatcher 作为订阅者,放到 subs 中
    // 防止重复订阅
    if(this.subs.indexOf(activeWatcher) === -1){
      this.subs.push(activeWatcher);
    }
  }
  notify() {
    // 先保存旧的依赖,便于下面遍历通知更新
    const deps = this.subs.slice()
    // 每次更新前,清除上一次收集的依赖,下次执行时,重新收集
    this.subs.length = 0;
    deps.forEach((watcher) => {
      watcher.update();
    });
  }
}

抽象 Observer

现在,WatcherDep只是两个独立的模块,我们怎么把它们关联起来呢?

答案就是Object.defineProperty,在数据被读取,触发get方法,Dep 将当前触发 get 的 Watcher 当做订阅者放到 subs中,Watcher 就与 Dep建立关系;在数据被修改,触发set方法,Dep就遍历 subs 中的订阅者,通知Watcher更新。

下面我们就来完善将数据转换为getter/setter的处理。

上面基础的响应式系统实现中,我们只定义了一个响应式数据,当 data 中有其他property时我们就处理不了了。所以,我们需要抽象一个 Observer类来完成对 data数据的遍历,并调用defineReactive转换为 getter/setter,最终完成响应式绑定。

为了简化,我们只处理data中单层数据。

class Observer {
  constructor(value) {
    this.value = value;
    this.walk(value);
  }
  // 遍历 keys,转换为 getter/setter
  walk(obj) {
    const keys = Object.keys(obj);
    for (let i = 0; i <p>这里我们通过参数 value 的闭包,来保存最新的数据,避免新增其他变量</p><pre class="brush:php;toolbar:false">function defineReactive(target, key, value) {
  // 每一个数据都是一个被观察者
  const dep = new Dep();
  Object.defineProperty(target, key, {
    enumerable: true,
    configurable: true,
    // 执行 data.xxx 时 get 触发,进行依赖收集,watcher 订阅 dep
    get() {
      if (activeWatcher) {
        // 订阅
        dep.addSubs(activeWatcher);
      }
      return value;
    },
    // 执行 data.xxx = xxx 时 set 触发,遍历订阅了该 dep 的 watchers,
    // 调用 watcher.updata 更新
    set(newValue) {
      // 如果前后值相等,没必要跟新
      if (value === newVal) {
        return;
      }
      value = newValue;
      // 派发更新
      dep.notify();
    },
  });
}

至此,响应式系统就大功告成了!!

测试

我们通过下面代码测试一下:

let data = {
  name: "张三",
  age: 18,
  address: "成都",
};
// 模拟 render
const render1 = () => {
  console.warn("-------------watcher1--------------");
  console.log("The name value is", data.name);
  console.log("The age value is", data.age);
  console.log("The address value is", data.address);
};
const render2 = () => {
  console.warn("-------------watcher2--------------");
  console.log("The name value is", data.name);
  console.log("The age value is", data.age);
};
// 先将 data 转换成响应式
new Observer(data);
// 实例观察者
new Watcher(render1);
new Watcher(render2);

在浏览器中运行这段代码,和我们期望的一样,两个render都执行了,并且在控制台上打印了结果。

Vue のレスポンシブ実装の原理について説明する記事

我们尝试修改 data.name = '李四 23333333',测试两个 render 都会重新执行:

Vue のレスポンシブ実装の原理について説明する記事

我们只修改 data.address = '北京',测试一下是否只有render 1回调都会重新执行:

Vue のレスポンシブ実装の原理について説明する記事

都完美通过测试!!?

总结

Vue のレスポンシブ実装の原理について説明する記事

Vue响应式原理的核心就是ObserverDepWatcher,三者共同构成 MVVM 中的 VM

Observer中进行数据响应式处理以及最终的WatcherDep关系绑定,在数据被读的时候,触发get方法,将 Watcher收集到 Dep中作为依赖;在数据被修改的时候,触发set方法,Dep就遍历 subs 中的订阅者,通知Watcher更新。

本篇文章属于入门篇,并非源码实现,在源码的基础上简化了很多内容,能够便于理解ObserverDepWatcher三者的作用和关系。

本文的源码,以及作者学习 Vue 源码完整的逐行注释源码地址:github.com/yue1123/vue…

(学习视频分享:web前端开发编程基础视频

以上がVue のレスポンシブ実装の原理について説明する記事の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事は掘金社区で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
React and Netflix:関係を探るReact and Netflix:関係を探るApr 26, 2025 am 12:11 AM

NetflixはReactを使用してユーザーエクスペリエンスを強化します。 1)Reactのコンポーネント機能は、Netflixが複雑なUIを管理可能なモジュールに分割するのに役立ちます。 2)Virtual DomはUIの更新を最適化し、パフォーマンスを向上させます。 3)ReduxとGraphQLを組み合わせて、Netflixはアプリケーションのステータスとデータフローを効率的に管理します。

vue.js vs.バックエンドフレームワーク:区別を明確にしますvue.js vs.バックエンドフレームワーク:区別を明確にしますApr 25, 2025 am 12:05 AM

Vue.jsはフロントエンドフレームワークであり、バックエンドフレームワークはサーバー側のロジックを処理するために使用されます。 1)VUE.JSは、ユーザーインターフェイスの構築に焦点を当て、コンポーネントおよびレスポンシブデータバインディングを介して開発を簡素化します。 2)ExpressやDjangoなどのバックエンドフレームワークは、HTTPリクエスト、データベース操作、ビジネスロジックを処理し、サーバーで実行します。

vue.jsとフロントエンドスタック:接続の理解vue.jsとフロントエンドスタック:接続の理解Apr 24, 2025 am 12:19 AM

VUE.JSは、開発効率とユーザーエクスペリエンスを向上させるために、フロントエンドテクノロジースタックと密接に統合されています。 1)建設ツール:Webpackおよびロールアップと統合して、モジュール開発を実現します。 2)国家管理:VUEXと統合して、複雑なアプリケーションステータスを管理します。 3)ルーティング:Vuerouterと統合して、単一ページのアプリケーションルーティングを実現します。 4)CSSプリプロセッサ:SASSをサポートし、スタイル開発効率を改善するために少なくなります。

Netflix:React(またはその他のフレームワーク)の使用の調査Netflix:React(またはその他のフレームワーク)の使用の調査Apr 23, 2025 am 12:02 AM

Netflixは、Reactのコンポーネント設計と仮想DOMメカニズムが複雑なインターフェイスと頻繁な更新を効率的に処理できるため、ユーザーインターフェイスを構築するためにReactを選択しました。 1)コンポーネントベースの設計により、Netflixはインターフェイスを管理可能なウィジェットに分解し、開発効率とコード保守性を向上させることができます。 2)仮想DOMメカニズムは、DOM操作を最小化することにより、Netflixユーザーインターフェイスの滑らかさと高性能を保証します。

vue.jsとフロントエンド:フレームワークに深く飛び込むvue.jsとフロントエンド:フレームワークに深く飛び込むApr 22, 2025 am 12:04 AM

Vue.jsは、使いやすく強力なため、開発者に愛されています。 1)そのレスポンシブデータバインディングシステムは、ビューを自動的に更新します。 2)コンポーネントシステムは、コードの再利用性と保守性を向上させます。 3)コンピューティングプロパティとリスナーは、コードの読みやすさとパフォーマンスを向上させます。 4)Vuedevtoolsの使用とコンソールエラーのチェックは、一般的なデバッグ手法です。 5)パフォーマンスの最適化には、主要な属性、計算された属性、およびキープアライブコンポーネントの使用が含まれます。 6)ベストプラクティスには、クリアコンポーネントの命名、単一ファイルコンポーネントの使用、ライフサイクルフックの合理的な使用が含まれます。

フロントエンドのvue.jsの力:主要な機能と利点フロントエンドのvue.jsの力:主要な機能と利点Apr 21, 2025 am 12:07 AM

Vue.jsは、効率的で保守可能なフロントエンドアプリケーションを構築するのに適した進歩的なJavaScriptフレームワークです。その主な機能には、1。レスポンシブデータバインディング、2。コンポーネント開発、3。仮想DOM。これらの機能を通じて、VUE.JSは開発プロセスを簡素化し、アプリケーションのパフォーマンスと保守性を向上させ、最新のWeb開発で非常に人気を博しています。

Vue.jsはReactよりも優れていますか?Vue.jsはReactよりも優れていますか?Apr 20, 2025 am 12:05 AM

Vue.jsとReactにはそれぞれ独自の利点と欠点があり、選択はプロジェクトの要件とチームの条件に依存します。 1)Vue.jsは、シンプルで使いやすいため、小さなプロジェクトや初心者に適しています。 2)Reactは、その豊富な生態系とコンポーネント設計のため、大規模なプロジェクトと複雑なUIに適しています。

Vue.jsの関数:フロントエンドでのユーザーエクスペリエンスの強化Vue.jsの関数:フロントエンドでのユーザーエクスペリエンスの強化Apr 19, 2025 am 12:13 AM

Vue.jsは複数の機能を介してユーザーエクスペリエンスを改善します。1。レスポンシブシステムは、リアルタイムデータフィードバックを実現します。 2。コンポーネント開発により、コードの再利用性が向上します。 3. Vuerouterはスムーズなナビゲーションを提供します。 4.動的データの結合および遷移アニメーションは、相互作用効果を強化します。 5.エラー処理メカニズムにより、ユーザーのフィードバックが保証されます。 6.パフォーマンスの最適化とベストプラクティスは、アプリケーションのパフォーマンスを改善します。

See all articles

ホット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衣類リムーバー

Video Face Swap

Video Face Swap

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

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター