如何获取 dom-if 或 dom-repeat 中的元素?
How to get element in dom-if or dom-repeat?
<dom-module id="weather-data">
<template>
<style is="custom-style" include="iron-flex iron-flex-alignment">
:host {
display: block;
font-family: Roboto;
}
paper-progress {
top: 0;
left: 0;
position: fixed;
width: 100%;
--paper-progress-active-color: var(--paper-light-blue-500);
--paper-progress-secondary-color: var(--paper-light-blue-100);
}
paper-icon-button {
margin: 0 auto;
margin-top: 20px;
display: block;
}
#weatherIcon {
width: 200px;
height: 200px;
}
table {
border-collapse: collapse;
}
table td {
text-align: center;
border: 1px solid #006064;
padding: 5px;
}
</style>
<paper-progress
id="request-progress"
indeterminate
hidden$="[[!activeRequest]]">
</paper-progress>
<iron-ajax
id="getData"
auto
url="[[weatherApiUrl]]"
handle-as="json"
last-response="{{weatherResponse}}"
last-error="{{error}}"
params="[[_getGegevensVanLocatie(coordinaten.latitude, coordinaten.longitude)]]"
loading="{{activeRequest}}">
</iron-ajax>
<template is="dom-if" id="tmp" if="[[weatherResponse]]">
<paper-icon-button
id="location-button"
disabled$="{{disableLocationButton}}"
on-tap="_getLocation"
icon="maps:my-location"
alt="Zoek mijn huidige locatie">
</paper-icon-button>
<div>
<div class="horizontal center-justified layout">
<h2>Weer voor locatie: <span>[[_maakLocationString(weatherResponse.query.results.channel.location)]]</span></h2>
</div>
<div class="horizontal center-justified layout">
<iron-icon
id="weatherIcon"
icon="[[_getIcon(weatherResponse.query.results.channel.item.condition.code)]]">
</iron-icon>
</div>
<div class="horizontal center-justified layout">
<h2>
<span>
[[weatherResponse.query.results.channel.item.condition.text]],
[[weatherResponse.query.results.channel.item.condition.temp]]° [[weatherResponse.query.results.channel.units.temperature]]
</span>
</h2>
</div>
<div class="horizontal center-justified layout">
<table>
<tr>
<td>
<iron-icon icon="icons:arrow-upward"></iron-icon>
</td>
<td>
<iron-icon icon="icons:arrow-downward"></iron-icon>
</td>
</tr>
<tr>
<td>[[weatherResponse.query.results.channel.astronomy.sunrise]]</td>
<td>[[weatherResponse.query.results.channel.astronomy.sunset]]</td>
</tr>
</table>
</div>
<div class="horizontal center-justified layout">
<h5 id="update-time">
Gegevens geraadpleegd om: [[weatherResponse.query.results.channel.item.condition.date]]<span></span>
</h5>
</div>
</div>
</template>
</template>
<script>
Polymer({
is: 'weather-data',
properties: {
weatherApiUrl: {
type: String,
value: "https://query.yahooapis.com/v1/public/yql"
},
coordinaten: {
type: Array,
value: {
longitude: 22,
latitude: 22
}
}
},
ready: function() {
if (navigator.permissions && navigator.permissions.query) {
navigator.permissions.query({
name: 'geolocation'
}).then(function(status) {
if (status.state === 'granted') {
console.log("Permisson already granted");
_getLocation();
} else {
console.log("Location not YET granted, using default coordinates");
if (status.state === "denied") {
console.log("Denied");
}
}
});
} else {
console.log("Permission not available");
console.log("Using standard coordinates");
}
},
_getLocation: function() {
console.log("Getting location");
},
_getGegevensVanLocatie: function(latitude, longitude) {
var latLong = '(' + 51.0339 + ',' + 3.7094 + ')';
return {
format: 'json',
q: 'select * from weather.forecast where woeid in ' +
'(select woeid from geo.places(1) where text="' + latLong + '") and u="c"'
};
},
_maakLocationString: function(location) {
if (location.city && location.region) {
return location.city + ', ' + location.region;
} else {
return location.city || 'Onbekend';
}
},
_getIcon: function(code) {
if (code >= 37 || code <= 12) {
return "image:flash-on";
}
if (code <= 18) {
return "image:flare";
}
if (code <= 30) {
return "image:wb-cloudy";
}
return "image:wb-sunny";
}
})
</script>
所以这是我的代码。我想要做的是在状态更改为授予时在导航器上授予权限时获取 <paper-icon-button>
元素。但是,这不适用于 this.$.location-button
或 this.$$('#location-button)
.
这是因为我在ready()
函数中使用了它吗?
Automated Node Finding 状态的 Polymer 文档:
Note: Nodes created dynamically using data binding (including those in dom-repeat
and dom-if
templates) are not added to the this.$
hash. The hash includes only statically created local DOM nodes (that is, the nodes defined in the element's outermost template).
因此,在您的情况下,您必须使用 this.$$('#location-button')
查询按钮,而不是使用 this.$['location-button']
。
我假设当您查询 #location-button
时布尔值 weatherResponse
是 false
,在这种情况下按钮将不存在于 DOM 中。如果在 ready()
中将布尔值设置为 true
,则在查询之前必须等待按钮在下一次渲染中被标记(使用 Polymer.RenderStatus.afterNextRender()
):
ready: function() {
this.weatherResponse = true;
Polymer.RenderStatus.afterNextRender(this, () => {
console.log(this.$$('#location-button'));
});
}
只有当 if
属性 为真时,dom-if
模板才会将其内容标记到 DOM 中。标记内容后,它只会在 if
属性 更改时隐藏和显示内容。尽管将 restamp
设置为 true
会破坏并重新创建内容。
因此,在您获取您的 weatherResponse
之前,您无法找到您的 paper-icon-button
,而它尚未在您的元素 ready
生命周期回调中完成。
Note that in the docs for polymers conditional templates usage it says:
Since it is generally much faster to hide and show elements rather than destroy and recreate them, conditional templates are only useful to save initial creation cost when the elements being stamped are relatively heavyweight and the conditional may rarely (or never) be true in given usages. Otherwise, liberal use of conditional templates can actually add significant runtime performance overhead.
因此,也许将您的 dom-if
模板更改为具有 hidden$="[[!weatherResponse]]"
属性的元素(例如 div
)更适合您的情况。这也会在调用 ready
时标记 paper-icon-button
。
<dom-module id="weather-data">
<template>
<style is="custom-style" include="iron-flex iron-flex-alignment">
:host {
display: block;
font-family: Roboto;
}
paper-progress {
top: 0;
left: 0;
position: fixed;
width: 100%;
--paper-progress-active-color: var(--paper-light-blue-500);
--paper-progress-secondary-color: var(--paper-light-blue-100);
}
paper-icon-button {
margin: 0 auto;
margin-top: 20px;
display: block;
}
#weatherIcon {
width: 200px;
height: 200px;
}
table {
border-collapse: collapse;
}
table td {
text-align: center;
border: 1px solid #006064;
padding: 5px;
}
</style>
<paper-progress
id="request-progress"
indeterminate
hidden$="[[!activeRequest]]">
</paper-progress>
<iron-ajax
id="getData"
auto
url="[[weatherApiUrl]]"
handle-as="json"
last-response="{{weatherResponse}}"
last-error="{{error}}"
params="[[_getGegevensVanLocatie(coordinaten.latitude, coordinaten.longitude)]]"
loading="{{activeRequest}}">
</iron-ajax>
<template is="dom-if" id="tmp" if="[[weatherResponse]]">
<paper-icon-button
id="location-button"
disabled$="{{disableLocationButton}}"
on-tap="_getLocation"
icon="maps:my-location"
alt="Zoek mijn huidige locatie">
</paper-icon-button>
<div>
<div class="horizontal center-justified layout">
<h2>Weer voor locatie: <span>[[_maakLocationString(weatherResponse.query.results.channel.location)]]</span></h2>
</div>
<div class="horizontal center-justified layout">
<iron-icon
id="weatherIcon"
icon="[[_getIcon(weatherResponse.query.results.channel.item.condition.code)]]">
</iron-icon>
</div>
<div class="horizontal center-justified layout">
<h2>
<span>
[[weatherResponse.query.results.channel.item.condition.text]],
[[weatherResponse.query.results.channel.item.condition.temp]]° [[weatherResponse.query.results.channel.units.temperature]]
</span>
</h2>
</div>
<div class="horizontal center-justified layout">
<table>
<tr>
<td>
<iron-icon icon="icons:arrow-upward"></iron-icon>
</td>
<td>
<iron-icon icon="icons:arrow-downward"></iron-icon>
</td>
</tr>
<tr>
<td>[[weatherResponse.query.results.channel.astronomy.sunrise]]</td>
<td>[[weatherResponse.query.results.channel.astronomy.sunset]]</td>
</tr>
</table>
</div>
<div class="horizontal center-justified layout">
<h5 id="update-time">
Gegevens geraadpleegd om: [[weatherResponse.query.results.channel.item.condition.date]]<span></span>
</h5>
</div>
</div>
</template>
</template>
<script>
Polymer({
is: 'weather-data',
properties: {
weatherApiUrl: {
type: String,
value: "https://query.yahooapis.com/v1/public/yql"
},
coordinaten: {
type: Array,
value: {
longitude: 22,
latitude: 22
}
}
},
ready: function() {
if (navigator.permissions && navigator.permissions.query) {
navigator.permissions.query({
name: 'geolocation'
}).then(function(status) {
if (status.state === 'granted') {
console.log("Permisson already granted");
_getLocation();
} else {
console.log("Location not YET granted, using default coordinates");
if (status.state === "denied") {
console.log("Denied");
}
}
});
} else {
console.log("Permission not available");
console.log("Using standard coordinates");
}
},
_getLocation: function() {
console.log("Getting location");
},
_getGegevensVanLocatie: function(latitude, longitude) {
var latLong = '(' + 51.0339 + ',' + 3.7094 + ')';
return {
format: 'json',
q: 'select * from weather.forecast where woeid in ' +
'(select woeid from geo.places(1) where text="' + latLong + '") and u="c"'
};
},
_maakLocationString: function(location) {
if (location.city && location.region) {
return location.city + ', ' + location.region;
} else {
return location.city || 'Onbekend';
}
},
_getIcon: function(code) {
if (code >= 37 || code <= 12) {
return "image:flash-on";
}
if (code <= 18) {
return "image:flare";
}
if (code <= 30) {
return "image:wb-cloudy";
}
return "image:wb-sunny";
}
})
</script>
所以这是我的代码。我想要做的是在状态更改为授予时在导航器上授予权限时获取 <paper-icon-button>
元素。但是,这不适用于 this.$.location-button
或 this.$$('#location-button)
.
这是因为我在ready()
函数中使用了它吗?
Automated Node Finding 状态的 Polymer 文档:
Note: Nodes created dynamically using data binding (including those in
dom-repeat
anddom-if
templates) are not added to thethis.$
hash. The hash includes only statically created local DOM nodes (that is, the nodes defined in the element's outermost template).
因此,在您的情况下,您必须使用 this.$$('#location-button')
查询按钮,而不是使用 this.$['location-button']
。
我假设当您查询 #location-button
时布尔值 weatherResponse
是 false
,在这种情况下按钮将不存在于 DOM 中。如果在 ready()
中将布尔值设置为 true
,则在查询之前必须等待按钮在下一次渲染中被标记(使用 Polymer.RenderStatus.afterNextRender()
):
ready: function() {
this.weatherResponse = true;
Polymer.RenderStatus.afterNextRender(this, () => {
console.log(this.$$('#location-button'));
});
}
只有当 if
属性 为真时,dom-if
模板才会将其内容标记到 DOM 中。标记内容后,它只会在 if
属性 更改时隐藏和显示内容。尽管将 restamp
设置为 true
会破坏并重新创建内容。
因此,在您获取您的 weatherResponse
之前,您无法找到您的 paper-icon-button
,而它尚未在您的元素 ready
生命周期回调中完成。
Note that in the docs for polymers conditional templates usage it says:
Since it is generally much faster to hide and show elements rather than destroy and recreate them, conditional templates are only useful to save initial creation cost when the elements being stamped are relatively heavyweight and the conditional may rarely (or never) be true in given usages. Otherwise, liberal use of conditional templates can actually add significant runtime performance overhead.
因此,也许将您的 dom-if
模板更改为具有 hidden$="[[!weatherResponse]]"
属性的元素(例如 div
)更适合您的情况。这也会在调用 ready
时标记 paper-icon-button
。