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
:null
param
:{ addedProperties, removedProperties }
addedProperties
:({ [property_name: string]: ProtoViewLogic | ProtoViewLogic[] })?
--- 新たにプロパティに追加されたProtoViewLogic
です。disrelateViewLogics()
の呼び出しではこの値は常にnull
になります。removedProperties
:({ [property_name: string]: ProtoViewLogic | ProtoViewLogic[] })?
--- プロパティから取り除かれたProtoViewLogic
です。
origin
:ProtoViewLogic
target
: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
でも送出されます。