我正在尝试创建一个注销页面,即使该元素已经连接到DOM之后也能正常工作。当您获得登录,然后注销,然后再次登录,并尝试退出时,就会发生这种情况。
例如,shell有
<iron-selector selected="[[page]]" attr-for-selected="name">
<a name="logout" href="[[rootPath]]logout">
<paper-icon-button icon="my-icons:sign-out" title="Logout" hidden$="[[!loggedIn]]"></paper-icon-button>
</a>
<a name="login" href="[[rootPath]]login">
<paper-icon-button icon="my-icons:sign-in" title="Login" hidden$="[[loggedIn]]"></paper-icon-button>
</a>
</iron-selector>
<<SNIP>>
<iron-pages selected="[[page]]" attr-for-selected="name" fallback-selection="view404" role="main">
<my-search name="search"></my-search>
<my-login name="login"></my-login>
<my-logout name="logout"></my-logout>
<my-view404 name="view404"></my-view404>
</iron-pages>
我还有一个关于shell中页面更改的观察者:
static get observers() {
return [
'_routePageChanged(routeData.page)',
];
}
_routePageChanged(page) {
this.loggedIn = MyApp._computeLogin();
if (this.loggedIn) {
this.page = page || 'search';
} else {
window.history.pushState({}, 'Login', '/login');
window.dispatchEvent(new CustomEvent('location-changed'));
sessionStorage.clear();
this.page = 'login';
}
}
这很有效,因为当我点击要注销的图标时,它会很好地附加my-logout
元素并执行ready()
或connectedCallback()
中的内容。
my-logout
已
ready() {
super.ready();
this._performLogout();
}
问题出现在没有刷新浏览器并导致DOM刷新的情况下,您重新登录并尝试再次注销。由于DOM从未清除过,my-logout
仍然附加,因此ready()
和connectedCallback()
都不会被激活。
我已经找到了解决这个问题的方法,但感觉非常糟糕。基本上,我可以在选择图标时为要执行this._performLogout();
的元素添加一个事件监听器:
ready() {
super.ready();
this._performLogout();
document.addEventListener('iron-select', (event) => {
if (event.detail.item === this) {
this._performLogout();
}
});
}
就像我说的,它有效,但我不喜欢有一个全局事件监听器,而且我必须在第一次元素附加和时调用logout函数我必须监听,因为监听器不是直到元件第一次连接后才有效。
答案 0 :(得分:1)
似乎没有“一刀切”的解决方案。中心问题是,“你想让父母告诉孩子,还是让孩子听父母的话?”。我在问题中提出的“答案”如果你想听父母,但因为我不喜欢全局事件监听器的想法,下面是如何使用<iron-pages>
到告诉一个子元素,它已被选中进行查看。
我们将selected-attribute
属性添加到<iron-pages>
:
<iron-pages selected="[[page]]" attr-for-selected="name" selected-attribute="selected" fallback-selection="view404" role="main">
<my-search name="search"></my-search>
<my-login name="login"></my-login>
<my-logout name="logout"></my-logout>
<my-view404 name="view404"></my-view404>
</iron-pages>
是的,考虑到attr-for-selected
属性,这看起来有点令人困惑。 attr-for-selected
说:“我应该使用my selected
属性的值将这些子元素与哪个属性匹配?”所以当我点击
<iron-selector selected="[[page]]" attr-for-selected="name">
<a name="logout" href="[[rootPath]]logout"><paper-icon-button icon="my-icons:sign-out" title="Logout" hidden$="[[!loggedIn]]"></paper-icon-button></a>
</iron-selector>
它会在内部将<my-logout>
设置为所选元素并显示它。 selected-attribute="selected"
做的是在子元素上设置属性。如果您查看浏览器JS控制台,您将看到该元素现在看起来像
<my-login name="login"></my-logout>
<my-logout name="login" class="iron-selected" selected></my-logout>
我们可以在检查更改的<my-logout>
元素中定义一个观察者
static get properties() {
return {
// Other properties
selected: {
type: Boolean,
value: false,
observer: '_selectedChanged',
},
};
}
_selectedChanged(selected) {
if (selected) {
this._performLogout();
}
}
if
语句是这样的,我们只在显示时触发逻辑,而不是在我们离开时。这样做的一个优点是我们不关心元素是否已经附加到DOM。当<iron-selector>/<iron-pages>
第一次选择<my-logout>
时,属性设置,元素附加,观察者触发,观察者看到selected
现在是true
(而不是定义的false
)并运行逻辑。