riot.pure
Riot v4.8.0でriot.pure
が追加されたので使ってみます。
コンポーネントのレンダリングを自分で制御したい場合に、riot.pure
を使うことで Riot.js の内部ロジックをスキップすることができるようです。
内部ロジックがスキップされる為、HTMLとCSSは使えません。
基本動作
riot.pureを使ってmount
、update
、unmount
のメソッドを含んだオブジェクトを返すモジュールを登録します。
<my-pure>
<script>
import { pure } from 'riot'
export default pure(({ slots, attributes, props }) => {
console.log(slots, attributes, props);
return {
el: null,
mount(el, context) {
this.el = el;
console.log("mount", el, context);
this.el.innerHTML = 'Hello There';
},
update(context) {
console.log("update", context);
},
unmount(preserveRoot) {
console.log("unmount", preserveRoot);
this.el.parentNode.removeChild(this.el);
}
};
});
</script>
</my-pure>
pure
で受け取れる内容は以下の3つ
-
slots
- コンポーネント内で見つかった slot リスト -
attributes
- コンテキストからコンポーネントプロパティを推測するために評価可能なコンポーネントの属性式 -
props
- riot.component 呼び出しによってのみ設定できる初期コンポーネントユーザープロパティ
pureの対象となるエレメントはマウント時にしかもらえないため、this.el
に保持しています。
pureコンポーネントの使用はこんな感じで。
<my-app>
<p>{ props.message }</p>
<my-pure></my-pure>
<input type="button" value="update" onclick="{ pre_update }">
<input type="button" value="unmount" onclick="{ pre_unmount }">
<script>
import { unmount } from 'riot'
export default {
pre_update(e) {
this.update();
},
pre_unmount(e) {
unmount('my-pure');
}
}
</script>
</my-app>
import { component,register } from 'riot'
import App from './app.riot'
import Pure from './pure.riot'
register('my-pure', Pure);
component(App)(document.getElementById('root'), {
message: 'Hello World'
});
試してみる…がunmount時に反応しない? -> <追記あり v4.8.7で修正済み>
どうやら、unmountの動きとしてriot-componentを持っていないとunmountを呼び出してくれないようです。
・動作確認用
https://plnkr.co/edit/sPjH1JE9zeLPErMBysx8?p=preview
というわけで、初めてのプルリクとやらをしてみました。1発ミスったのは内緒。
https://github.com/riot/riot/pull/2801
修正内容はいたって簡単で、持っていないなら持たせればいいじゃない、の精神。
return createCoreAPIMethods(method => (...args) => {
component[method](...args)
args[0][IS_PURE_SYMBOL] = component // ここ追加
return component
})
export function unmount(selector, keepRootElement) {
return $(selector).map(element => {
if (element[DOM_COMPONENT_INSTANCE_PROPERTY]) {
element[DOM_COMPONENT_INSTANCE_PROPERTY].unmount(keepRootElement)
// ↓ ここ追加
} else if (element[IS_PURE_SYMBOL]) {
element[IS_PURE_SYMBOL].unmount(keepRootElement)
}
return element
})
}
1/20 追記
プルリクは却下されてしまいました(さすがに修正内容が安直すぎた)が、Issueで修正してもらえました!
https://github.com/riot/riot/issues/2806
v4.8.7でunmountもRiot.jsから呼んでもらえるようになっています。
まとめ
これを使えば複数のコンポーネントで使いまわせる共通の処理とか書けそう。