vue2データの双方向バインディングを理解するには、手で入力するとよりよく理解できるようになります~
1. ページデータの一部
データ双方向バインディングを実装する前に、まず使用する必要のあるデータを準備し、次にコード部分を実装します。
(1) ページ構成
ここでは、 vue の双方向データ バインディングの効果を実現するために、 v-model によってバインドされたデータとページ構造の補間式の値の間の相関関係を完了する必要があります。
<body id="app">
<span>up主:{
{ name }}</span>
<input type="text" v-model="name">
<span>更多:{
{ more.like }}</span>
<input type="text" v-model="more.like">
</body>
(2)スクリプト部
スクリプト タグ部分を通じてインポートされた vue ファイルは、実際の vue ではありません。つまり、すぐに作成するコード部分です。
el では、将来の便宜のために、HTML 部分の <body/> タグに ID を保存します。
<script src="./vue.js"></script>
<script>
const vm = new Vue(
{
el: '#app',
data: {
name: 'kerwin',
more: {
like: '点赞'
}
}
}
)
console.log(vm);
</script>
2 つ目は、vue.js コード
(1) Vueインスタンスを作成する
コード量が比較的多く、コンストラクターを使用する必要があるため、コンストラクターを作成するクラス class を選択します。
まず、obj_instance がインスタンスの場合に渡されるオブジェクト。まずデータ属性をインスタンスの $dataに保存しますが、これは vue でも使用されます
class Vue {
constructor(obj_instance) {
this.$data = obj_instance.data
}
}
(2) データハイジャックを実現
キーポイント:データハイジャックを実現するには Object.defineProperty を使用する必要があります。これは vue2 の場合ですが、vue3 は少し異なります。vue2 を理解した後、vue3 を理解することは難しくありません。
1. データハイジャック機能を作成する
双方向バインディングに必要なのはデータ内のデータであるため、データを渡す必要があります。
class Vue {
constructor(obj_instance) {
// ....
// 在构造函数中将data 传入
Observer(this.$data)
}
}
// 实现数据劫持
function Observer(data_instance) {
}
2. データオブジェクトを走査し、データハイジャックを実装する
理解:Object.defineProperty
Object.defineProperty( 操作のオブジェクト, 操作のプロパティ, { } )
{ } オブジェクトを渡し、オブジェクト内でデータ監視を実装します。
このメソッドは、オブジェクト内の既存のプロパティを変更できます。
// 数据劫持
function Observer(data_instance) {
// 遍历对象中的每一个属性
Object.keys(data_instance).forEach(key => {
Object.defineProperty(data_instance, key, {
// 设置属性描述符可以改变
configurable: true,
// 设置是否可枚举
enumerable: true,
get() {
},
set(newValue) {
},
})
})
}
3. セッターとゲッターを設定する
設定前にコンソールでデータを確認できます
①ゲッター
オブザーバーの前に vm を出力してみましょう。vm の属性値にアクセスすると、アクセス時に を取得しても返されないため、データが未定義であることがわかり、データが失われます。
したがって、キーをトラバースするときは、まずデータを value 変数に保存し、それにアクセスすると get がトリガーされて値が返されるため、データは正常になります。
②セッター
vm にデータを設定すると、set 関数がトリガーされ、その仮パラメータ (newValue) が設定したデータであるため、値を newValue として直接設定でき、この時点でデータは通常どおり変更できます。
// 数据劫持
function Observer(data_instance) {
// 如果没有值或不为对象那么直接返回出去
Object.keys(data_instance).forEach(key => {
++ let value = data_instance[key]
Object.defineProperty(data_instance, key, {
configurable: true,
enumerable: true,
get() {
++ console.log(`访问了${key}属性 --> 属性值为:${value}`);
++ return value // 将原本数据return出来
},
set(newValue) {
++ value = newValue
++ console.log(`修改了${key}属性值${value} --> 为${newValue}`);
},
})
})
}
4. データオブジェクト属性のオブジェクトを処理する
設定した data 属性値にはオブジェクトも含まれているため、object.key を使用して最初のレイヤーのみを走査します。data 内のすべてのデータをハイジャックしたい場合は、再帰を使用する必要があります。
キーを走査するときは、まず再帰的に呼び出してオブジェクトとして値またはデータ型があるかどうかを確認し、存在する場合は再帰を続けてこの問題を解決します。
function Observer(data_instance) {
// 如果没有值或不为对象那么直接返回出去
++ if (!data_instance || typeof data_instance !== 'object') return
Object.keys(data_instance).forEach(key => {
let value = data_instance[key]
// 递归,内部属性
++ Observer(value)
Object.defineProperty(data_instance, key, {
// ....
})
})
}
5. 新しいオブジェクトをプロパティに割り当てるハンドル
プロパティをオブジェクトに再割り当てする場合、observ はすでに実行されているため再帰されません。そのため、セッターで再度 observ を呼び出す必要があります。
Object.defineProperty(data_instance, key, {
// ...
set(newValue) {
// 递归
++ Observer(newValue)
value = newValue
return console.log(`修改了${key}属性值${value} --> 为${newValue}`);
},
})
多すぎるので説明は省略します、後ほど追記します
詳細は gitee を参照して clone してください。アドレスは以下の通りです
Vue2 はデータの双方向バインディングを実装します: Vue2 のデータの双方向バインディング、v-model+input をカバーします