Vue2.x の応答性の簡単な説明と例

Vue2.x の応答性の簡単な説明と例

1. Vue レスポンシブの使用法を確認する

​ Vue の応答性は、私たち全員がよく知っています。 Vue のデータ オブジェクト内のプロパティを変更すると、ページ内でプロパティが参照される場所もそれに応じて変更されます。これにより、DOM を操作してデータ バインディングを実行する必要がなくなります。

2. Vue レスポンシブ実装の分析

Vue のレスポンシブ原則については、公式 Web サイトにテキストによる説明があります (https://cn.vuejs.org/v2/guide/reactivity.html)。

Vueは主にデータハイジャックとオブザーバーモードを通じて実装されています

データハイジャック:

vue2.x は内部的に Object.defineProperty を使用します https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

vue3.x が内部で使用するプロキシ https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy

オブザーバーパターン: https://www.jb51.net/article/219790.htm

内部メンバー図

各メンバーの機能

ビュー:

データのメンバーをVueインスタンスに注入し、データのメンバーをゲッターとセッターに変換します。

オブザーバー:

データオブジェクト内の単純型データとオブジェクトを監視し、データが変更されたときにDepに通知します。

コンパイラ:

各要素の命令/差分式を解析し、対応するデータに置き換えます

出発地:

オブザーバーモードでの通知機能、オブザーバーの追加、データの変更時にオブザーバーに通知する

ウォッチャー:

データ内のプロパティを参照する各場所には、ビューの更新を担当するウォッチャーオブジェクトがあります。

付録: データオブジェクト内のプロパティは観測対象として機能し、データオブジェクト内のプロパティが参照される場所は観測者として機能します。

3. Vue レスポンシブ ソースコード実装

Vueオブジェクトの実装

関数

  • 初期化パラメータの受け入れを担当
  • データ内の属性をデータインスタンスに注入し、ゲッターとセッターに変換する
  • データ内のすべての属性の変更を監視するためにObserverを呼び出す
  • コンパイラを呼び出して、命令と差分式を解析します。
クラス Vue{
    コンストラクタ(オプション){
        // 1. 渡された属性を属性を通じて保存します。this.$options= options||{};
        this.$data = オプション.data||{};
        this.$el = typeof options.el ==='string' ? document.querySelector(options.el) : options.el;
        // 2. データパラメータのデータをゲッターとセッターに変換し、Vue インスタンスにマウントします。this._proxyData(this.$data)
        // 3. データの変更を監視するために observe オブジェクトを呼び出します new Observer(this.$data)
        // 4. コンパイラオブジェクトを呼び出してページをレンダリングする new Compiler(this)
    }
    _proxyData(データ){
        if (data&&Object.keys(data).length>0){
             for (const キー in データ) {
                Object.defineProperty(this,key,{
                    設定可能:true、
                    列挙可能:true、
                    得る(){
                        データを返す[キー]
                    },
                    設定(値){
                        if (データ[キー]===値) {
                            戻る;
                        }
                        データ[キー]=値;
                    }
                })
             }
        }
    }
}

オブザーバーオブジェクトの実装

関数

  • データオプションの属性をハイジャックする
  • データ内の属性もオブジェクトである場合は、それを再帰的にレスポンシブオブジェクトに変換します。
  • データが変更されたときに通知を送信する
//データハイジャッククラスObserver {
    コンストラクタ(データ) {
        this.walk(データ)
    }
    ウォーク(データ) { 
        //1. データがオブジェクトかどうかを判定する if (!data || typeof data !== 'object') {     
            戻る
        }
        //2. ループ呼び出しdefineReactiveでdataObject.keys(data).forEach(key => {をハイジャックする
            this.defineReactive(データ、キー、データ[キー])
        })
    }
    定義Reactive(オブジェクト、キー、値) {
        //通知機能を作成する const dep = new Dep()
        //参照オブジェクトのプロパティをレスポンシブにするには、walk を使用します。this.walk(val)
        const は、次のようになります。
        Object.defineProperty(obj, キー, {
            設定可能: true、
            列挙可能: true、
            得る() {
                //Notifier はオブザーバーを収集します Dep.target && dep.addSub(Dep.target)
                戻り値:
            },
            set(newVal) {
                (newVal === val)の場合{
                    戻る;
                }
                val = 新しいVal;
                that.walk(新しい値)
                // 監視対象オブジェクトが変更されると、通知オブジェクトは各オブザーバーに通知を送信します dep.notify()
            }
        })
    }
}

オブジェクト実装をコンパイルする

関数

  • テンプレートのコンパイル、命令の解析、微分表現を担当
  • ページの最初のレンダリングを担当
  • データが変更されたときにビューを再レンダリングする責任がある
//コンパイラクラス Compiler {
    コンストラクタ(vm) {
        this.el = vm.$el;
        this.vm = vm;
        this.compile(this.el)
    }
    //テンプレートをコンパイルして、ノードがテキストノードか要素ノードかを判断する compile(el) {
        childNodes を el.childNodes とします。
        //子ノードの最初の層を処理する Array.from(childNodes).forEach(node ​​=> {
            if (this.isTextNode(ノード)) {
                this.compileText(ノード)
            } それ以外の場合は (this.isElementNode(node)) {
                this.compileElement(ノード)
            }
            //現在のノードに子ノードがある場合は、コンパイル命令を再帰的に呼び出します。if (node.childNodes && node.childNodes.length) {
                this.compile(ノード)
            }
        })
    }

    //要素ノードをコンパイルし、命令を処理する compileElement(node) {  
        //すべての命令を走査する Array.from(node.attributes).forEach(attr => {
            //ディレクティブノードかどうかを判断します if (this.isDirective(attr.name)) {
                定数 nodeName = attr.name;
                定数キー = attr.nodeValue;
                const ディレクティブ = nodeName.substr(2)
                this.updater(ディレクティブ、ノード、キー)
            }
        }) 
    }
    アップデータ(ディレクティブ、ノード、キー){
        const updaterFn = this[ディレクティブ+"Updater"]
        updaterFn && updaterFn.call(this,node,this.vm[key],key)
    }
    //vテキスト
    textUpdater(ノード、値、キー){
        node.textContent=値
        //v-text式が使用される場所はオブザーバーです new Watcher(this.vm,key,newValue => {
            node.textContent = 新しい値
        })
    }
    //vモデル
    modelUpdater(ノード、値、キー){
        ノード.値 =値
        //v-model式が使用される場所はオブザーバーです new Watcher(this.vm,key,newValue => {
            node.value = 新しい値
        })
      //双方向バインディングを実現するnode.addEventListener('input',()=>{
            this.vm[キー] = ノード.値
        })
    }
    //v-html
    htmlUpdater(ノード、値、キー){
        node.innerHTML = 値
        //v-html式が使用される場所はオブザーバーです new Watcher(this.vm,key,newValue => {
            node.innerHTML = 新しい値
        })
    }

    //差分式の処理 compileText(node) {
        //正規表現の一致の違い let reg = /\{\{(.+?)\}\}/
        //正規表現を使用してノードのテキストコンテンツと一致させ、一致する場合は置き換えます if (reg.test(node.textContent)) {
            //補間式のキーを取得する
            キーを RegExp.$1 とします。
            値を node.textContent とします。
            node.textContent = value.replace(reg, this.vm[key])

            //差分式が使用される場所はオブザーバーです new Watcher(this.vm,key,newValue => {
                node.textContent = 新しい値
            })
        }
    }

    //ディレクティブかどうか isDirective(attrName) {
        attrName.startsWith('v-') を返します。
    }

    //テキストノードかどうか isTextNode(node) {
        node.nodeType === 3 を返します
    }

    //要素かどうか isElementNode(node) {
        node.nodeType === 1 を返します
    }
}

依存関係オブジェクトの実装

関数

  • 依存関係を収集し、オブザーバーを追加する
  • すべての観察者に通知する
//通知クラスclass Dep {
    コンストラクタ() {
        //ストレージオブザーバー this.subs = []
    }

    /**
     * オブザーバーを集める */
    サブルーチンを追加します。
        if (sub && sub.update) {
            this.subs.push(サブ)
        }
    }

    /**
     * 状態の変化をオブザーバーに通知する */
    通知() {
        this.subs.forEach(sub => {
            サブ.更新()
        })
    }
}

ウォッチャーオブジェクトの実装

関数

  • データが変更されると、DepはすべてのWatcherインスタンスにビューを更新するように通知します。
  • 自身をインスタンス化するときに、自身をDepオブジェクトに追加する
//オブザーバークラスクラス Watcher {
    コンストラクタ (vm,key,cb) {
        //Vue インスタンス this.vm =vm;
        //データ内のキーオブジェクト this.key =key;
        // ビューを更新するためのコールバック関数 this.cb = cb
        //現在のオブザーバーインスタンスをDepのターゲット静的プロパティに保存します。Dep.target = this
        //Observe の getter メソッドをトリガーし、現在のインスタンスを Dep.subs に保存します //データ内のキーに対応する古い値 this.oldValue = this.vm[this.key]
        依存関係ターゲット = null
    }
    //各オブザーバーには状態を変更するための更新メソッドがあります update(){
        const newValue = this.vm[this.key]
        if ( this.newValue === this.oldValue ) {
            戻る
        }
        this.cb(新しい値)
    }
}

テスト

<ヘッド>
    <メタ文字セット="UTF-8">
    <meta http-equiv="X-UA-compatible" content="IE=edge">
    <meta name="viewport" content="width=デバイス幅、初期スケール=1.0">
    <title>インデックス</title>
    <script src="./js/dep.js"></script>
    <script src="./js/watcher.js"></script>
    <script src="./js/compiler.js"></script>
    <script src="./js/observer.js"></script>
    <script src="./js/vue.js"></script>
</head>
<本文>
    <p id="アプリ">
        <h1>差分式</h1>
        <h3>{{メッセージ}}</h3>
        <h3>{{カウント}}</h3>
        <h1>v-テキスト</h1>
        <p v-text='メッセージ'></p>
        <h1>vモデル</h1>
        <input type="text" v-model="msg" attr="msg">
        <input type="text" v-model="count">
        <h1>v-html</h1>
        <p v-html="htmlテキスト"></p>
    </p>
    <スクリプト>
        vm = new Vue({
            el:"#アプリ",
            データ:{
                メッセージ: '情報',
                count:'数量', 
		人:{name:'张三'},
                htmlText:"<p style='color:red'>こんにちは</p>"
            }
        })
    </スクリプト>
</本文>

これで、Vue2.x のレスポンシブ性の簡単な説明と例についての記事は終了です。Vue2.x のレスポンシブ性に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Vue2 レスポンシブシステム非同期キュー
  • Vue2 レスポンシブ システムの紹介
  • Vue2 レスポンシブシステム ブランチ切り替え
  • Vue2 レスポンシブシステムのネスト
  • Vue2 レスポンシブシステム: ディープレスポンス
  • Vue2 レスポンシブ システム アレイ
  • Vue2 レスポンシブ システムの設定と削除
  • vue2 の応答性の欠点

<<:  MySQLデータベースはMMM高可用性クラスタアーキテクチャを実装します

>>:  Docker で Nginx イメージ サーバーを構築する方法

推薦する

Kali に docker と portainer をインストールする方法

dockerの登場により、多くのサービスが徐々にハードウェアアーキテクチャへの依存から脱却しました。...

Ubuntu のインストール グラフィック ドライバーと Cuda チュートリアル

目次1. 元のドライバーをアンインストールする2. 新しいグラフィックカードドライバーをダウンロード...

Alibaba Cloud ホストが IP を使用して Web サイトにアクセスできない問題の解決策 (セキュリティ グループ ルールを構成することで解決)

Alibaba Cloud ホストを購入したばかりで、その速度を試すのが待ちきれませんでした。しか...

マインスイーパゲームを実装するための jQuery プラグイン (2)

この記事では、jQueryプラグインを使用してマインスイーパゲームを実装する2番目の記事を参考までに...

CSS3で実装された天気アイコンのアニメーション効果

成果を達成する 実装コードhtml <div class="wrapper"...

Windows での MySQL 8.0.15 の詳細なインストールと使用のチュートリアル

この記事では、MySQL 8.0.15の詳細なインストールと使用方法のチュートリアルを参考までに紹介...

HTML と CSS の命名規則の概要

CSS命名規則 ヘッダー: ヘッダーコンテンツ: コンテンツ/含むフッターナビゲーション: navサ...

よく使われるn番目の子セレクターをまとめる

序文フロントエンドプログラミングでは、奇数、偶数などの数値を受け入れることができる nth-chil...

CSS3 でのシンプルな LED デジタル時計の実装方法

これは多くの人がやったことがあるはずです。ただうずうずして書きたかったので、時間をかけていじってダー...

Ubuntu 14 に Nginx-RTMP ストリーミング サーバーをインストールするチュートリアル

1. RTMP RTMP ストリーミング プロトコルは、Adobe が開発したリアルタイムのオーディ...

Vue のすべてのカプセル化方法の簡単な概要

目次1. カプセル化API 2. グローバルツールコンポーネントを登録する3. グローバル関数をカプ...

CSS 複合セレクタの具体的な使用法

交差点セレクター交差セレクターは、直接接続された 2 つのセレクターで構成されます。最初のセレクター...

uniapp プロジェクトで MQTT を使用する方法

目次1. uniappプラグインマーケットのリファレンスプラグイン2. 具体的な導入プロセス1. m...

VMware での Ubuntu 16.04 イメージの完全インストール チュートリアル

この記事では、VMware 12でのUbuntu 16.04イメージのインストールチュートリアルを参...

HTML初心者や初級者向けの提案。専門家は無視してかまいません。

感想:私はバックエンド開発者です。静的 (HTML) ページを取得すると、ページ構造と命名規則が極端...