こんにちは、私は Xiao Suoqi です。慎重に作成された Vue シリーズは継続的にリリースされており、多数の経験と例がカバーされています。必要に応じて収集できます。この章では、データの監視について説明します。前の章は更新されており
、次の章が続きます。出力、質問がある場合は、メッセージを残すかプライベートメッセージを送信してください、一緒に働きましょう~
データ監視
Vue のデータ監視実装の核心は、defineProperty() を介してプロパティのゲッターとセッターをハイジャックすることです。データ データを取得するとき、最下層はゲッターとセッターを呼び出すことによって実装されます。プロパティが取得されたときに追加の操作を実行できます。読み取りまたは変更されます。これは実際には、データ オブジェクトが「プロキシ」されて、いわゆる「応答データ」を形成します。
より具体的には、コンポーネントを初期化するときに、Vue はデータ オブジェクトのすべてのプロパティを走査し、Object.defineProperty を使用してそれらをゲッター/セッターに変換します。このプロキシにより、Vue は依存関係を追跡し、プロパティがアクセスおよび変更されたときに変更を通知できます (VM)のデータは _data からのデータ プロキシです)
たとえば、message という名前のデータ属性を定義すると、Vue はそれを次のように変換します。
Object.defineProperty(data, 'message', {
get () {
// ...进行依赖收集
},
set (newValue) {
// ...触发更新
}
})
このように、メッセージの読み取りまたは変更時に、ゲッターとセッターがトリガーされて、依存関係の収集と更新のトリガーが実行される可能性があり、これらは直接データ ハイジャックと呼ばれます。
データ ハイジャックは Vue の応答性の基礎であり、データの変更を検出し、コールバックをトリガーしてビューの更新を完了できるため、開発者は DOM を手動で操作せずにデータ自体に集中するだけで済みます。
なぜここでデータハイジャックについて言及されているのでしょうか?
一言で言えば、データハイジャックは手段であり、データ監視が目的です(データハイジャックがなければ、データの変更を正確に監視できません)
具体的に下を見てみましょう、以下のポイントと組み合わせて見てください、わからなかったらまた登ってください。
小規模な応答性の高いシステムがどのように動作するかをシミュレートします。
<div id="app">
<!-- 视图渲染 -->
</div>
<script>
// 数据对象
const data = {
name: 'John',
age: 20
};
function reactive(obj) {
// 汇总所有obj形成一个数组并进行遍历
// 核心响应式转换代码
Object.keys(obj).forEach(key => {
let value = obj[key];
const dep = new Set();
Object.defineProperty(obj, key, {
get() {
// 收集依赖
dep.add(updateView);
return value;
},
set(newVal) {
// 更新值
value = newVal;
// 触发依赖更新
dep.forEach(fn => fn());
}
});
});
return obj;
}
// 数据响应式处理
const reactiveData = reactive(data);
// 视图更新函数
function updateView() {
// ...渲染视图
}
// 初始化
updateView();
// 数据改变时触发视图更新
reactiveData.name = "Bob";
</script>
この応答性の高いシステムはビューを自動的に更新できます
属性値が取得されるとサブスクライバーが収集され、属性値が設定されるとサブスクライバーにビューを更新するように通知されます。
get と set を行わないと、応答データがなく、ページに表示されません。(デバッグ ページ内の括弧は、その存在を証明しており、get または set なしで直接定義されたものはページに応答しません)
拡大する
レスポンシブ変換が理解できないかも?
// 响应式转换
const reactiveData = reactive(data);
reactive 関数は、通常のオブジェクトを応答オブジェクトに変換するために使用され、共通オブジェクトをパラメーターとして受け取り、このオブジェクトのすべてのプロパティに対して応答処理を実行し、応答オブジェクトを返します。
それでここで
const data = {
name: 'John',
age: 20
};
共通のオブジェクトデータを定義することです
移行:
const reactiveData = reactive(data);
リアクティブ関数はデータ オブジェクトのすべてのプロパティを走査し、Object.defineProperty() を使用してこれらのプロパティをゲッター/セッター形式に変換します。
データ オブジェクトと同じプロパティを持ちますが、レスポンシブ関数の追加により、データの代わりに ResponseData を使用し、ビューを自動的に更新できるようにします。
簡単に言うと、reactive(data) 行の機能は、通常のオブジェクト データを応答オブジェクト reactiveData に変換し、データの監視と更新の表示を実装できる応答データ オブジェクトを取得することです。
プロパティは直接監視されるため、オブジェクトの階層構造が深すぎる場合、内部プロパティの変更が応答をトリガーしないことに注意してください。これには、オブジェクトを完全に置き換えるか、新しい値を手動で設定する必要があります。
data: {
user: {
name: 'John',
friend: {
name: 'Chris'
}
}
}
このように friends.name が直接変更された場合、Vue はそれを検出できません (深いプロパティの直接変更は検出できません。Vue の応答性はプロパティのゲッターとセッターをハイジャックすることによって実現されますが、ハイジャックできるのは、オブジェクト〜)
this.user.friend.name = '小索奇'
重要: ユーザー オブジェクト全体を置き換えるか、Vue.set | this.$set を使用して friends.name を変更し、応答性の高いデータにして有効にする必要があります。
// 非响应式
this.user.name = '小索奇'
// 响应式
// Vue.set(target, key, value) | this.$set(target, key, value)
this.$set(this.user.friend, 'name', '小索奇')
配列についても同様で、配列のインデックス値は変更できないことに注意してください (配列自体には get メソッドや set メソッドがありません)。
this.list[0] = 'A'
// 如果数组下有对象属性,可以更改
this.list[0].name = '小索奇'
配列を変更するには、Vue.set を使用してインデックスを変更するか、配列独自のプッシュ、ポップ、シフト、シフト解除、スプライス、ソート、リバースなどの API を使用するなど、Vue のグローバル API を直接呼び出す必要があります。
- これらのメソッドは Vue によってラップされているため、ビューの更新を実行できます。
上記はスプライスに置き換えることができます
this.list.splice(start, deleteCount, item1)
非同期関数でデータが変更された場合、ページはすぐには更新されず、非同期関数が完了するまで新しいデータはページに表示されません。
setTimeout(() => {
this.message = 'hello'
}, 1000)
したがって、タイマーや ajax などを使用してデータを変更すると、後でページが更新されます。
Vue のデータ監視で注意すべき点は次のとおりです。
- 深くネストされたデータは、Vue.set または完全に置き換える必要があります。
- 配列インデックスは、Vue.set または array メソッドを使用して変更する必要があります。
- 非同期関数でデータを変更するとページの更新が遅れます。
拡大する
Vue.set(ターゲット,キー,値)
// vm.$set()
Vue.set(vm._data.obj,'country','China')
// 为什么等同于下面的
Vue.set(vm.obj,'country','China')
これはデータブローカーのレビューによるものです。
Vue.set
リアクティブ オブジェクトにプロパティを追加し、新しいプロパティもリアクティブであることを確認するメソッド
Vue が初期化されると、data
オブジェクトが Vue インスタンスにプロキシされるため、vm.obj
次のアクセスと同じになります。vm._data.obj
つまり、コンポーネント インスタンス ではVM
、 access は元のデータ オブジェクトにプロキシされるため、vm.obj
access と同等になります。vm._data.obj
_data
これは、大まかに次のようなVue のメソッドを通じてproxy
実現されます。
function proxy(vm) {
Object.keys(vm._data).forEach(key => {
Object.defineProperty(vm, key, {
get() {
return vm._data[key];
}
});
});
}
したがって、Vue.set
メソッドは元の_data
オブジェクトまたはプロキシされたコンポーネント インスタンス オブジェクトのいずれかを受け入れることができ、効果は同じです。
それらはすべて同じ元のデータ オブジェクトを指します
知らせ
- ターゲットを VM インスタンスにすることはできません。また、データなどの直接のルート オブジェクトにすることもできません。
フォーム入力バインディング
ここではナンセンスではありません。早速本題に入りましょう。
次の場合<input type="text"/>
、v-model は値を収集し、ユーザーが入力したものが値になります。
次の場合<input type="radio"/>
、v-model は value 値を収集し、その value 値をラベルに対して構成する必要があります。
もし:<input type="checkbox"/>
- 入力の value 属性が構成されていない場合、収集される内容がチェックされます (チェックされているかどうか、ブール値です)。
input の value 属性を設定します。
-
v-model の初期値は配列ではないため、収集される内容はチェックされます (チェックされるかチェックされないか、ブール値です)。
-
v-model の初期値は配列であるため、収集されるのは値で構成される配列です。
v-model はデフォルトで値を収集します。vue で設定された内容を収集するには、値を記述する必要があります。それ以外の場合は、デフォルト値が収集されます (たとえば、チェックボックスのデフォルトは selected-boolean)。
Vue のフォーム要素にデフォルト値をバインドする一般的な例は次のとおりです。
ラジオボタンのバインド文字列値
// 不设置value默认读取null
<input type="radio" v-model="picked" value="A">
<script>
data() {
return {
picked: 'A'
}
}
</script>
チェックボックスバインディングのブール値:
// checkbox 必须设置value值,不设置的话默认为checked的状态(布尔值)
// 如果有多组值,需要把绑定的数据设置为数组,
睡觉<input type="checkbox" v-model="hobby" value="sleep">
玩<input type="checkbox" v-model="hobby" value="play">
吃<input type="checkbox" v-model="hobby" value="eat">
<script>
data() {
hobby:[]
}
</script>
ボックスバインド文字列を選択します:
<select v-model="selected">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<script>
data() {
return {
selected: 'A'
}
}
</script>
テキスト入力バインド文字列:
<input v-model="message">
<script>
data() {
return {
message: ''
}
}
</script>
さらに、次のような、より実用的な機能が学習を待っています。
- 計算されたプロパティを使用してフォーム入力値を処理し、データの前処理や書式設定を実行します。
- 使用される
v-model
修飾子( や.number
など)は.trim
、必要に応じて入力を自動的に変換または変更できます。
次節も頑張ってください〜