ページ全体をRiotで作っている場合はあまり問題にならないかもしれませんが、「HTMLの中にRiotタグが散在している」かつ「Riotのマウントと別な箇所でタグを使った処理をしたい」というような状況下では、「あとからページにセットしたRiotタグのオブジェクトを取得したい」という場面が生じてきます。
これは、Riotのデータ構造をたどることで実現可能です。
Riotのデータ構造
グローバルにある状況であればグローバルのriot
、const riot = require('riot');
としている場合はそのriot
を使えますが、riot.util.vdom
に、ページへマウントしたタグオブジェクトが配列となって入っています。
そして、タグオブジェクト自体(で、今回のテーマに関係するもの)には、以下のプロパティがあります。
-
tag.root
…対応するDOMノード -
tag.tags[子タグ名]
…このタグの中に存在する別のRiotタグ。1個ならタグオブジェクトがそのまま入っていて、複数なら配列となっている。
ということで、riot.util.vdom
からtags
を再帰的にたどれば目的のことをできそうです。
実際に書いてみた
get_riot_tag.js
// WeakMapがある場合はキャッシュさせる
let cache = null;
if(window.WeakMap){
cache = new WeakMap;
}
function getRiotTag(elem, current = riot.util.vdom) {
if(typeof elem === 'string') {
// セレクタで回せるように
elem = document.querySelector(elem);
}
if(cache) {
const cached = cache.get(elem);
if(cached) return cached;
}
let ret = null;
if(Array.isArray(current)) {
// 最初のvdom、あるいはtagsが配列だった時
current.some(item => {
ret = getRiotTag(elem, item);
return ret;
});
} else {
// currentがタグの場合
// キャッシュに入れる
if(cache) cache.set(current.root, current);
// 自分自身をチェック
if(current.root === elem) return current;
for(const key in current.tags) {
ret = getRiotTag(elem, current.tags[key]);
if(ret) return ret;
}
}
return ret;
}
なお、「何度も走査するのを避ける」のと「DOMがなくなればキャッシュも確実に破棄させる」ために、WeakMap
でキャッシュさせています。