ProtoViewLogic: relateViewLogics()
与えられた ProtoViewLogic を子とする親子関係を結びます。
構文
protoViewLogic.relateViewLogics(protoViewLogicMap) => object
引数
-
protoViewLogicMap:object|Promise<object>子として追加する
ProtoViewLogicとその名前を対応づけるオブジェクト、または履行時にそれを与えるPromiseです。各プロパティは
ProtoViewLogicインスタンスかProtoViewLogicインスタンスの配列です。 それぞれのプロパティ名は対象のViewLogicインスタンスに追加するプロパティの名前として使われます。
返値: object | Promise<object>
対象の ProtoViewLogic から親子関係が解消された ProtoViewLogic をプロパティに持つオブジェクト、または履行時にそれを与える Promise です。
オブジェクトのプロパティ名は、親子関係が解消された ProtoViewLogic が以前に持っていた名前(name 参照)です。
引数 protoViewLogicMap のプロパティと同名の ProtoViewLogic が既に親子関係を結んでいる場合、既存の ProtoViewLogic の親子関係が解消(disrelateViewLogics() 参照)されます。
返値のオブジェクトは Object を継承していません(null-prototype object です)。
例外
TypeError- 引数
protoViewLogicMapがProtoViewLogicのインスタンスだった場合。 - 引数
protoViewLogicMapのプロパティにProtoViewLogicでもProtoViewLogic[]でもない値が設定されていた場合。
- 引数
ReferenceError- 引数
protoViewLogicMapのプロパティに対象のProtoViewLogic自身またはその祖先が含まれる場合。循環参照を作ってしまうためエラーとなります。 - 引数
protoViewLogicMapのプロパティとして、同一のProtoViewLogicが異なる複数のプロパティ名で指定されている場合。
- 引数
SyntaxError- 引数
protoViewLogicMapのプロパティ名がいずれかの条件に当てはまる場合:- 識別子として使用できない文字を含む
- 空文字列
- 既に
relateElements()で関連付けられた要素に使用されている
- 引数
例
import { ProtoViewLogic } from "/alier_sys/ProtoViewLogic.js";
console.group("Example of ProtoViewLogic.relateViewLogics()");
const Watcher = class extends ProtoViewLogic {
async messageHandler(msg) {
console.groupCollapsed(`${msg.id}+${msg.code}`);
console.log("%cmsg.id :", "font-weight: bold; font-family: monospace;", msg.id);
console.log("%cmsg.code :", "font-weight: bold; font-family: monospace;", msg.code);
console.log("%cmsg.origin :", "font-weight: bold; font-family: monospace;", msg.origin);
console.log("%cmsg.target :", "font-weight: bold; font-family: monospace;", msg.target);
console.log("%cmsg.param :", "font-weight: bold; font-family: monospace;", msg.param);
console.log("%cmsg.param?.state :", "font-weight: bold; font-family: monospace;", msg.param?.state);
console.log("%cmsg.param?.newName :", "font-weight: bold; font-family: monospace;", msg.param?.newName);
console.log("%cmsg.param?.newParent :", "font-weight: bold; font-family: monospace;", msg.param?.newParent);
console.log("%cmsg.param?.oldName :", "font-weight: bold; font-family: monospace;", msg.param?.oldName);
console.log("%cmsg.param?.oldParent :", "font-weight: bold; font-family: monospace;", msg.param?.oldParent);
console.log("%cmsg.param?.addedProperties :", "font-weight: bold; font-family: monospace;", msg.param?.addedProperties);
console.log("%cmsg.param?.removedProperties:", "font-weight: bold; font-family: monospace;", msg.param?.removedProperties);
console.groupEnd();
}
};
const vl = new Watcher;
const foo = new Watcher;
const bar = [
new Watcher,
new Watcher
];
console.groupCollapsed("step-1");
// (1) foo, bar を vl の子にする;
// vl に同名の子はいないので空のオブジェクトが返る
console.log("eval: vl.relateViewLogics({ foo, bar })");
console.log("==> ", vl.relateViewLogics({ foo, bar }));
// ==> {}
console.groupEnd();
console.groupCollapsed("step-2");
// (1) foo, bar を vl の子にする;
// vl に同名の子はいないので空のオブジェクトが返る
foo.relateViewLogics({ baz: vl3 });
// ==> "connection state = "\disconnected\"; old name = \"bar\"; new name = null;"
// ==> "connection state = "\connected\"; old name = \"bar\"; new name = \"baz\";"
console.groupEnd();
bar.relateViewLogics({ foo: vl2 });
// ==> なにも行われない(vl2.parent === vl1 であり vl2.name === "foo" のため)
console.groupEnd();
解説
引数 protoViewLogicMap として渡されたオブジェクトのプロパティを対象の ProtoViewLogic へコピーし、各プロパティが持つ ProtoViewLogic と親子関係を結びます。
子の ProtoViewLogic に post() で送られたメッセージが消費されなかった場合は親の ProtoViewLogic にメッセージが送られます。また、親の ProtoViewLogic に broadcast() で送られたメッセージは子の ProtoViewLogic に送られます。
relateViewLogics() の呼び出し先の ProtoViewLogic は、引数の各プロパティが持つ ProtoViewLogic の親となります。
引数として与えられた ProtoViewLogic の parent プロパティに呼び出し先の ProtoViewLogic への参照が設定されます。また、子となる ProtoViewLogic の name プロパティには、引数のオブジェクトに設定されたプロパティ名が設定されます。
const vl = new ProtoViewLogic();
const foo = new ProtoViewLogic();
const bar = new ProtoViewLogic();
vl.relateViewLogics({ foo, bar });
console.log(foo.parent === vl);
// => true
console.log(bar.parent === vl):
// => true
console.log(foo.name);
// => "foo"
console.log(bar.name);
// => "bar"
既に同名のプロパティが存在し、そのプロパティが relateViewLogics() によって関連付けられた ProtoViewLogic だった場合、既存の ProtoViewLogic の親子関係は解消されます。子だった ProtoViewLogic の parent プロパティおよび name プロパティの値は null に変更されます。
const vl = new ProtoViewLogic();
const foo = new ProtoViewLogic();
const bar = new ProtoViewLogic();
vl.relateViewLogics({ foo });
console.log(foo.parent === vl);
// => true
console.log(foo.name);
// => "foo"
// foo を vl_bar に付け替え
vl.relateViewLogics({ foo: bar });
console.log(foo.parent === vl);
// => false
console.log(foo.name);
// => null
メッセージ
メッセージの概要についてはメッセージパッシングを、他のメッセージについては ViewLogic の状態変更を通知するメッセージを参照してください
vl$connectionChanged
relateViewLogics() によって子の ProtoViewLogic の parent プロパティの値が変更されると、メッセージ { id: "vl$connectionChanged" } が変更を受ける ProtoViewLogic に対して post() されます。
メッセージ内容は以下の通りです:
-
id:"vl$connectionChanged" -
code:null -
param:{ state, oldParent, oldName, newParent, newName }-
state:"connected"|"disconnected"--- 対象のProtoViewLogicが他のProtoViewLogicの子になったら"connected"が、子でなくなったら"disconnected"が設定されます。noteすでに親を持っている
ProtoViewLogicをrelateViewLogics()に渡したとき、内部ではまず親子関係を解消してから新しく親子関係を結んでいます。なのでメッセージは"disconnected"と"connected"が順番に送出されます。 -
oldParent:ProtoViewLogic|null--- 直前まで設定されていたparentプロパティの値です。 -
oldName:string|null--- 直前まで設定されていたnameプロパティの値です。 -
newParent:ProtoViewLogic--- 新たに設定されたparentプロパティの値です。relateViewLogics()では常に呼び出し先のProtoViewLogicになります。 -
newName:string--- 新たに設定されたnameプロパティの値です。
-
-
origin:ProtoViewLogic -
target:ProtoViewLogic
const parent = new ProtoViewLogic;
const child = new class extends ProtoViewLogic {
async messageHandler(msg) {
if (msg.id === "vl$connectionChanged") {
console.log(`new name: ${msg.param.newName}`);
}
}
};
parent.relateViewLogics({ foo: child });
// => 以下がログ出力されます:
// new name: foo
メッセージ { id: "vl$connectionChanged" } は disrelateViewLogics() でも送出されます。
vl$propertiesModified
この関数の呼び出し後、対象の ProtoViewLogic から自身に対してプロパティ id として vl$propertiesModified を値に持つメッセージが送られます。このメッセージが持つプロパティは以下の通りです:
id:"vl$propertiesModified"code:nullparam:{ addedProperties, removedProperties }addedProperties:({ [property_name: string]: ProtoViewLogic | ProtoViewLogic[] })?--- 新たにプロパティに追加されたProtoViewLogicです。disrelateViewLogics()の呼び出しではこの値は常にnullになります。removedProperties:({ [property_name: string]: ProtoViewLogic | ProtoViewLogic[] })?--- プロパティから取り除かれたProtoViewLogicです。
origin:ProtoViewLogictarget:ProtoViewLogic
const parent = new class extends ProtoViewLogic {
async messageHandler(msg) {
if (msg.id === "vl$propertiesModified") {
if (msg.param.addedProperties != null) {
const addedKeys = Object.keys(msg.param.addedProperties)
console.log(`added properties: ${JSON.stringify(addedKeys)}`);
}
}
}
};
const child = new ProtoViewLogic;
parent.relateViewLogics({ bar: child });
// => 以下がログ出力されます:
// added properties: ["bar"]
メッセージ { id: "vl$propertiedModified" } は disrelateViewLogics でも送出されます。