censor(object, extra)
Description
ライフサイクル属性と指定されたカスタム属性が取り除かれた、shallow copyされたオブジェクトを返します。
javascript
var attrs = { one: 'two', enabled: false, oninit: function () {} };
var censored = m.censor(attrs, ['enabled']);
// {one: "two"}
Signature
censored = m.censor(object, extra)
Argument | Type | Required | Description |
---|---|---|---|
object | Object | Yes | 文字列に変換可能なキーと値のマップ。 |
extra | Array<String> | No | 省略する追加のプロパティの配列。 |
returns | Object | 省略するプロパティが存在しない場合は元のオブジェクトが、それ以外の場合は削除されたプロパティを持つshallow copyされたオブジェクトが返されます。 |
How it works
通常、このメソッドは必須ではありません。必要な属性のみを明示的に指定する方が一般的です。しかし、場合によっては、未知の属性をすべて別の要素に渡す方が便利なことがあります。これは多くの場合合理的ですが、ライフサイクルメソッドが意図せず複数回呼び出されてしまうという問題を引き起こす可能性があります。
javascript
function SomePage() {
return {
view: function () {
return m(SomeFancyView, {
oncreate: function () {
sendViewHit(m.route.get(), 'some fancy view');
},
});
},
};
}
function SomeFancyView() {
return {
view: function (vnode) {
return m('div', vnode.attrs, [
// !!!
// ...
]);
},
};
}
一見問題ないように見えますが、実際には問題が発生します。このビューにアクセスするたびに、sendViewHit
が2回実行されてしまいます。ここで m.censor
が役立ちます。これを使用すると、属性から oncreate
を削除し、1回だけ呼び出されるようにすることで、呼び出し元は予期せぬバグに悩まされることなく開発を進めることができます。
javascript
// Fixed
function SomeFancyView() {
return {
view: function (vnode) {
return m('div', m.censor(vnode.attrs), [
// ...
]);
},
};
}
key
属性でも同様の問題が発生する可能性があります。
javascript
function SomePage() {
return {
view: function () {
return m(
Layout,
{
pageTitle: 'Some Page',
key: someKey,
},
[
// ...
]
);
},
};
}
function Layout() {
return {
view: function (vnode) {
return [
m('header', [m('h1', 'My beautiful web app'), m('nav')]),
m('.body', vnode.attrs, [
// !!!
m('h2', vnode.attrs.pageTitle),
vnode.children,
]),
];
},
};
}
これは最終的にエラーをスローします。Mithril.jsが Layout
vnodeを作成するときに認識する内容は次のとおりです。
javascript
return [
m('header', [m('h1', 'My beautiful web app'), m('nav')]),
m('.body', { pageTitle: 'Some Page', key: someKey }, [
m('h2', 'Some Page'),
[
/* ... */
],
]),
];
特に、間接参照や他の要因が絡み合っている現実的なシナリオでは、一見しただけでは気づきにくいことがあります。これを修正するには、同様に key:
属性を削除する必要があります。カスタムの pageTitle
属性も削除できます。これはDOMに含めても意味がないためです。
javascript
// Fixed
function Layout() {
return {
view: function (vnode) {
return [
m('header', [m('h1', 'My beautiful web app'), m('nav')]),
m('.body', m.censor(vnode.attrs, ['pageTitle']), [
m('h2', vnode.attrs.pageTitle),
vnode.children,
]),
];
},
};
}