vue.js----ライフサイクル---インスタンス属性、イベントの初期化


一、初期化インスタンス属性
(1)Vue.jsのライフサイクル全体において、インスタンス属性の初期化が最初のステップである.
(2)インスタンス化が必要な属性には、Vue.js内部で使用する属性(vm._watcherなど)と、外部で使用する属性(vm.$parentなど)があります.
(3)$で開発された属性は,ユーザに提供される外部属性であり,先頭のプロパティは、内部で使用される内部プロパティです.
(4)Vue.jsはinitLifecycle関数を介してインスタンスに属性をマウントし、この関数はVue.jsインスタンスをパラメータとして受信する.したがって、関数では、Vue.jsインスタンスにプロパティを設定するだけで、Vue.jsインスタンスにプロパティをマウントする目的を達成できます.
(5)実現
export function initLifecycle(vm){
	const options = vm.$options;
	
	let parent = options.parent;
	if(parent&&!options.abstract){
		while(parent.$options.abstract&&parent.$parent){
			parent = parent.$parent;
		}
		parent.$children.push(vm);
	}
	vm.$parent = parent;
	vm.$root = parent? parent.$root : vm;

	vm.$children = [];
	vm.$refs = {};

	vm._watcher = null;
	vm._isDestroyed = false;
	vm._isBeingDestroyed = false;
}

1.Vue.jsインスタンスにいくつかの属性を設定し、デフォルト値を指定します.
2、vm.$parentプロパティは、最初の非抽象タイプの親を見つける必要があるため、コードでは、現在のコンポーネントが抽象コンポーネントでなく、親が存在する場合、whileを介して下から上へループする必要があると判断されます.親が抽象クラスである場合は、最初の非抽象クラスの親に遭遇するまで、vm.$parentプロパティに値を割り当てます.
3、vm.$childrenプロパティ.現在のインスタンスの直接サブコンポーネントが含まれます.このプロパティの値は、子コンポーネントから親コンポーネントにアクティブに追加されます.parent.$children.push(vm)は、親コンポーネントインスタンスの$childrenプロパティに現在のインスタンスを追加します.
4、vm.$root、現在のコンポーネントツリーのルートVue.jsインスタンスを識別します.現在のコンポーネントに親コンポーネントがない場合、それ自体がルートコンポーネントであり、その$root属性はそれ自身であり、そのサブコンポーネントのvm.$root属性は親レベルの$rootに沿っているので、その直接サブコンポーネントの$root属性はそれか、その孫コンポーネントの$root属性はその直接サブコンポーネントの$root属性に沿って、このように推定されます.したがって、これは、ルートコンポーネントの$rootを各サブコンポーネントに上から下へ順次渡すプロセスである.
二、初期化イベント
(1)初期化イベントとは、親コンポーネントがテンプレートで使用するv-on登録のイベントをサブコンポーネントのイベントシステム(Vue.jsのイベントシステム)に追加することである.
(2)Vue.jsでは、親コンポーネントは、サブコンポーネントを使用する場所でv-onを使用して、サブコンポーネントがトリガしたイベントをリスニングすることができる.
(3)テンプレートコンパイルフェーズでは、v-onまたは@を使用して登録されたイベントを含むラベル上のすべての属性を得ることができる.
(4)テンプレートのコンパイル段階では、テンプレート全体をレンダリング関数にコンパイルしますが、レンダリング関数は、要素ノードを作成するためにネストされた関数です.
(5)要素ノードを作成する関数は次のとおりです:c(tagName,data,children).
(6)レンダープロセスが開始されると、レンダー関数が実行され、VNodeが生成され、仮想DOMはVNodeを使用してレンダーされます.
(7)この過程でいくつかの要素が作成されますが、現在のラベルが本物のラベルなのかコンポーネントなのかが判断されます.
(8)コンポーネントラベルの場合、サブコンポーネントはインスタンス化され、テンプレートにv-onを使用してサブコンポーネントラベルに登録された親コンポーネントのイベントを含むパラメータが渡されます.
(9)プラットフォームラベルの場合、要素を作成してDOMに挿入し、ラベルにv-onで登録されたイベントをブラウザイベントに登録します.
(10)すなわち、v-onがコンポーネントラベルに書かれている場合、このイベントはサブコンポーネントVue.jsイベントシステムに登録される.divなどのプラットフォームラベルに書かれている場合、イベントはブラウザイベントに登録されます.
(11)サブコンポーネントは、初期化時、すなわちVue.jsインスタンスを初期化すると、親コンポーネントがサブコンポーネントに登録したイベントを受信する可能性がある.サブコンポーネント自体がテンプレートに登録されているイベントは、レンダリング時にのみ仮想DOMの比較結果に基づいて登録イベントかバインド解除イベントかを決定します.したがって、インスタンス初期化フェーズでは、初期化されたイベントとは、親コンポーネントがテンプレート内でv-onを使用してサブコンポーネント内でトリガーされたイベントをリスニングすることを意味する.
(12)Vue.jsはinitEvents関数により初期化イベントに関する論理を実行する.
export function initEvents(vm){
	vm._events = Object.create(null);
	
	const listeners = vm.$options._parentListeners;
	if(listeners){
		updateComponentListeners(vm,listeners);
	}
}

1、vmに追加_eventsプロパティは、イベントを格納するために空のオブジェクトに初期化されます.実際、vm.$onを使用して登録されたすべてのイベントリスナーはvm._に保存されます.eventsプロパティ.
2、 テンプレートコンパイルフェーズでは、テンプレートがコンポーネントラベルに解析されると、サブコンポーネントがインスタンス化され、ラベルに登録されているイベントがobjectに解析され、パラメータによってサブコンポーネントに渡されます.したがって、サブコンポーネントがインスタンス化されると、親コンポーネントが自分に登録したイベントをパラメータで取得できます.これらのイベントは最終的にvm.$options._に保存されます.parentListenersにあります.

vm.$options._parentListeners:
{ increment :function(){}}

3、vm.$options.parentListenersが空でない場合、updateComponentListenersメソッドを呼び出し、親コンポーネントがサブコンポーネントに登録したイベントをサブコンポーネントインスタンスに登録します.
(13)updateComponentListenersロジック
vm.$options._をループするだけです.parentListeners vm.$onを使用してイベントをthis._に登録します.イベントでいいです.
let target;

function add(event,fn,once){
	if(once){
		target.$once(event,fn);
	}else{
		target.$on(event,fn);
	}
}

function remove(event,fn){
	target.$off(event,fn);
}

export function updateComponentListeners(vm,listeners,oldListeners){
	target = vm;
	updateListeners(listeners,oldListeners || {},add,remove,vm);
}

1、addとremoveの2つの関数をカプセル化し、イベントを追加および削除します.
2、updateListeners関数listenersとoldListenersの違いを比較し、パラメータに指定されたaddとremoveを呼び出して、対応する登録イベントとアンインストールイベントの操作を行う.
(14)updateListeners関数
1、実現構想:listenersオブジェクトにkey(すなわちイベント名)がoldListenersに存在しない場合、このイベントは新規のイベントが必要であることを説明する.逆に、listenersにoldListenersにキー(イベント名)が存在しない場合は、イベントシステムから削除する必要があることを示します.
export function updateListeners(on,oldOn,add,remove,vm){
	let name,cur,old,event;
	for(name in on){
		cur = on[name];
		old = oldOn[name];
		event = normalizeEvent(name);
		if(isUndef(cur)){
			process.env.NODE_ENV!=='production' && warn(
				'Invaild handler for event "${event.name}":got'+String(cur),
				vm
			)
		}else if(isUndef(old)){
			if(isUndef(cur.fns)){
				cur = on[name] = createFnInvoker(cur);
			}
			add(event.name,cur,event.once,event.capture,event.passive);
		}else if(cur!==old){
			old.fns = cur;
			on[name] = old;
		}
	}
	for(name in oldOn){
		if(isUndef(on[name])){
			event = normalizeEvent(name);
			remove(event.name,oldOn[name],event.capture);
		}
	}
}

2、この関数は5つのパラメータを受け取り、それぞれon、oldOn、add、remove、vmである.
3、その主なロジックはonとoldOnよりどのイベントがadd登録イベントを実行する必要があるのか、どのイベントがremove削除イベントを実行する必要があるのかを見分けることである.
4、二つの部分に分けることができますね.第一部分はループonで、第二部分はループoldOnです.第1部の主な役割は、oldOnに存在しないイベントを判断し、addを呼び出してこれらのイベントを登録することです.第2部の役割はoldOnをループし、onに存在しないイベントを判断し、removeを呼び出してこれらのイベントを除去することである.
5、ループonの過程において、次の3つの判断がある
  • は、イベント名に対応する値がundefinedまたはnullであるかどうかを判断し、もしそうであればコンソールで警告をトリガーする.
  • は、そのイベント名がoldOnに存在するかどうかを判断し、存在しない場合はadd登録イベントを呼び出す.
  • イベント名がonとoldOnの両方に存在するが、それらが異なる場合、イベントコールバックはonのコールバックに置き換えられ、onのコールバックリファレンスは実際のイベントシステムに登録されているイベント、すなわちoldOnの対応するイベントを指す.

  • 6.isUndef関数は、入力されたパラメータがundefinedまたはnullであるかどうかを判断するために使用される.
    (15)normalizeEvent関数
    1、Vue.jsのテンプレートでは、capture、once、passiveなどのイベント修飾子がサポートされています.テンプレートにイベントを登録するときにイベント修飾子を使用すると、テンプレートコンパイルフェーズでラベルのプロパティを解析するときに、これらの修飾子が対応するシンボルに変更され、イベント名の前にロードされます.たとえば、

    vm.$options._parentListenersは次のとおりです.
    {~increment:function(){}}

    イベント名の前に~記号が追加され、そのイベントのイベント修飾子がonceであることを示し、現在のイベントがイベント修飾子を使用しているか否かを判別する.
    2、normalizeEventの役割はイベント修飾子を解析することである.
    const normalizeEvent = name =>{
    	const passive = name.charAt(0) === '&';
    	name = passive ? name.slice(1) : name;
    	const once = name.charAt(0) === '~';
    	name = once ? name.slice(1) : name;
    	const capture = name.charAt(0) === '!';
    	name = capture ? name.slice(1) : name;
    	return{
    		name,
    		once,
    		capture,
    		passive
    	}
    }

    3、イベントに修飾子がある場合は、それを切り取ります.最終的に出力されたオブジェクトには、true説明イベントにこのイベント修飾子が使用されているイベント名と、いくつかのイベント修飾子が保存されます.