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

php中世界最好的语言
リリース: 2018-05-23 13:51:04
オリジナル
1872 人が閲覧しました

今回は、Vue のデータ応答性を実装する方法と、Vue のデータ応答性を実装するための 注意点 について説明します。以下は実際的なケースです。見てみましょう。

前書き

Vue のデータ応答は主に Object.defineProperty() に依存していますが、全体のプロセスはどのようなものですか?私たち独自のアイデアで Vue の道を歩むということは、実際には、Vue の原則をエンドポイントとして採用することを意味します。実装プロセスを逆にしましょう。

この記事のコードはすべてロープロファイル バージョンであり、多くの箇所は厳密ではありません。たとえば、if(typeof obj === 'object') は、obj がオブジェクトである可能性もありますが、obj がオブジェクトであるかどうかを判断します。

array などのデータですが、この記事では簡単のため、array の場合は Array.isArray() を使用して判定オブジェクトを表現します。

データの変換

まずオブジェクトを変換する関数を書いてみましょう:

なぜ最初にこの関数を書く必要があるのでしょうか? データの変換は最も基本的で重要な手順であるため、後続のすべての手順はこの手順に依存します。

// 代码 1.1
function defineReactive (obj,key,val) {
 Object.defineProperty(obj,key,{
  enumerable: true,
  configurable: true,
  get: function () {
   return val;
  },
  set: function (newVal) {
   //判断新值与旧值是否相等
   //判断的后半段是为了验证新值与旧值都为NaN的情况 NaN不等于自身
   if(newVal === val || (newVal !== newVal && value !== value)){
    return ;
   }
   val = newVal;
  }
 });
}
ログイン後にコピー
たとえば、 const obj = {} として、defineReactive(obj,'a',2) メソッドを呼び出します。このとき、関数内では、val=2 となり、毎回 obj.a の値が返されます。 obj.aの設定時にvalの値も設定されます。 (defineReactive が呼び出されるたびに、val の値を保存するためのクロージャが生成されます);

プロセスディスカッション

検証の結果、この関数は実際に使用できることがわかりました。次に、応答プロセスについて説明します。

  1. データを入力

  2. データを変換 (defineReactive())

  3. データが変更された場合 => イベントをトリガー

3 番目のステップを見てみましょう。 1. データの変更はどのように後続のイベントをトリガーしますか?よく考えてください。データを変更したい場合は、最初にデータを設定する必要があります。その後、メソッドを set() に追加するだけで問題ありません。

次に、別の重要な質問があります:

Dependency Collection

データ変更後にどのイベントがトリガーされるかをどのようにして知ることができるのでしょうか? Vue の場合:

Use data => View; データはビューのレンダリングに使用されるため、Vue はデータ属性を変換して依存関係を収集するときに、依存関係を収集するのに最適なタイミングです。

// 代码 1.2
class Dep {
 constructor(){
  //订阅的信息
  this.subs = [];
 }
 addSub(sub){
  this.subs.push(sub);
 }
 removeSub (sub) {
  remove(this.subs, sub);
 }
 //此方法的作用等同于 this.subs.push(Watcher);
 depend(){
  if (Dep.target) {
   Dep.target.addDep(this);
  }
 }
 //这个方法就是发布通知了 告诉你 有改变啦
 notify(){
  const subs = this.subs.slice()
  for (let i = 0, l = subs.length; i < l; i++) {
   subs[i].update();
  }
 }
}
Dep.target = null;
ログイン後にコピー
コード 1.2 は、当面は 2 つのメソッドの機能を理解するだけで済みます

  1. --- その他の側面では、依存イベントを収集すると理解できます。は考慮されず、この関数は addSub ()

  2. notify() と同等です --- このメソッドはより直観的であり、依存するすべての update() メソッドを実行します。後でビューを変更するだけです。

この記事では主にデータ応答のプロセスについて説明し、Watcher クラスについては詳しく説明しません。そのため、Dep.1 のメソッドの機能を知っていれば十分です。

それでは、コード 1.1 を変更します

//代码 1.3
function defineReactive (obj,key,val) {
 const dep = new Dep();
 Object.defineProperty(obj,key,{
  enumerable: true,
  configurable: true,
  get: function () {
   if(Dep.target){
    //收集依赖 等同于 dep.addSub(Dep.target)
    dep.depend()
   }
   return val;
  },
  set: function (newVal) {
   if(newVal === val || (newVal !== newVal && val !== val)){
    return ;
   }
   val = newVal;
   //发布改变
   dep.notify();
  }
 });
}
ログイン後にコピー
このコードには疑問があります。Dep.target とは何ですか?依存関係を収集するために Dep.target が必要なのはなぜですか?

  1. Dep はクラスであり、Dep.target はクラスの属性であり、dep インスタンスの属性ではありません。

  2. Dep クラスはグローバルに利用できるため、Dep.target にグローバルにアクセスでき、その値を任意に変更できます。

  3. get メソッドの使用は非常に一般的であり、データ値を取得するために毎回 dep.depend() を呼び出すことは不可能です。

  4. dep.depend() は実際には dep.addSub(Dep.target) です。

  5. その場合、使用前に Dep.target をオブジェクトに設定し、サブスクリプションの完了後に Dep.target = null を設定するのが最善の方法です。

検証

コードの波が利用可能かどうかを検証する時が来ました

//代码 1.4
const obj = {};//这一句是不是感觉很熟悉 就相当于初始化vue的data ---- data:{obj:{}};
//低配的不能再低配的watcher对象(源码中是一个类,我这用一个对象代替了)
const watcher = {
 addDep:function (dep) {
  dep.addSub(this);
 },
 update:function(){
  html();
 }
}
//假装这个是渲染页面的
function html () {
 document.querySelector('body').innerHTML = obj.html;
}
defineReactive(obj,'html','how are you');//定义响应式的数据
Dep.target = watcher;
html();//第一次渲染界面
Dep.target = null;
ログイン後にコピー

此时浏览器上的界面是这样的

然后在下打开了控制台开始调试,输入:

obj.html = 'I am fine thank you'
ログイン後にコピー

然后就发现,按下回车的那一瞬间,奇迹发生了,页面变成了

结尾

Vue数据响应的设计模式和订阅发布模式有一点像,但是不同,每一个dep实例就是一个订阅中心,每一次发布都会把所有的订阅全部发布出去。

Vue的响应式原理其实还有很大一部分,本文主要讨论了Vue是如何让数据进行响应,但是实际上,一般的数据都是很多的,一个数据被多处使用,改变数据之后观察新值,如何观察、如何订阅、如何调度,都还有很大一部分没有讨论。主要的三个类Dep(收集依赖)、Observer(观察数据)、Watcher(订阅者,若数据有变化通知订阅者),都只提了一点点。

之前写有一篇Vue响应式----数组变异方法,针对Vue中对数组的改造进行讨论。当然之后有更多其他的文章,整个数据响应流程还有很多内容,三个主要的类都还没有讨论完。

其实阅读源码不仅仅是为了知道源码是如何工作的,更重要的是学习作者的思路与方法,我写的文章都不长,希望自己能够每次专注一个点,能够真真实实领悟到这一个点的原理。当然也想控制阅读时间,免得大家看到一半就关闭了。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

怎样用React Form完成组件封装

ES6中Promise使用步骤详解

以上がVue データの応答性を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!