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オブジェクトの実装 関数
クラス 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 => {
サブ.更新()
})
}
} ウォッチャーオブジェクトの実装 関数
//オブザーバークラスクラス 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 をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: MySQLデータベースはMMM高可用性クラスタアーキテクチャを実装します
>>: Docker で Nginx イメージ サーバーを構築する方法
設定手順Linux システム: CentOS-7.0 MySQL バージョン: 5.7.21 Lin...
序文この記事では、div の幅を 100% に設定し、親要素を超えてパディングまたはマージンを設定す...
目次1. はじめに: 2. プロトタイプチェーン継承: 3. コンストラクタ継承の借用(オブジェクト...
目次1. サービスの開始と停止の手順1.1 Windows での MySQL 5.7 の公式 MSI...
序文ほとんどの人は、システム ディスク ストレージが少ないときにこの操作を実行するか、Linux シ...
まず、いくつかの概念を明確にします。 JDBC: Javaデータベース接続、Oricalによって規定...
基本概念操作の前に、まずいくつかの基本的な概念を理解する必要がありますディスクLinux システムで...
1. 基本概念1. Sitemeshはページ装飾技術です。 1 : フィルターを通してページアクセス...
目次1 テスト環境1.1 サーバーハードウェア1.1.1 t2.マイクロ1.1.2 c5.large...
この記事では、例を使用して、MySQL でストアド プロシージャを作成し、データ テーブルに新しいフ...
https をサポートしていない Web サイトは、ブラウザによって徐々に安全でないとマークされるた...
1. テーブル構造 2. 表データ 3. クエリのteacher_nameフィールドは空にすることは...
Centos7では、/etc/rc.d/rc.localファイルの権限が削減されており、実行権限があ...
質問まず、私が遭遇した問題についてお話しします。まず、そういった需要があるわけです。フロントエンドは...
1. MYSQLに接続するフォーマット: mysql -h ホストアドレス -u ユーザー名 -p ...