censor(object, extra)
描述
返回一个对象的浅克隆,该对象会省略生命周期属性以及任何指定的自定义属性。
javascript
var attrs = { one: 'two', enabled: false, oninit: function () {} };
var censored = m.censor(attrs, ['enabled']);
// {one: "two"}
签名
censored = m.censor(object, extra)
参数 | 类型 | 必需 | 描述 |
---|---|---|---|
object | Object | 是 | 键值对对象。 |
extra | Array<String> | 否 | 需要排除的额外属性的名称数组。 |
返回 | Object | 如果原始对象上不存在需要省略的属性,则返回原始对象;否则,返回一个删除了指定属性的浅克隆对象。 |
工作原理
通常情况下,你可能不需要这个方法,只需要明确指定你需要的属性即可。但有时,将所有未知的属性传递给另一个元素会更方便。这在很多情况下是合理的,但可能会导致一个潜在的问题:生命周期方法被调用两次。
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
函数会被调用两次。m.censor
的作用就在于此:它允许你从属性中移除 oncreate
等生命周期方法,从而确保它们只被调用一次,避免调用者遇到难以调试的错误。
javascript
// 修复后的代码
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
// 修复后的代码
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,
]),
];
},
};
}