HTML要素の配列をbodyへ挿入しリアクティブに更新したい《VanJS》
配列の所でハマりましたが、解決したので書き残します。
前回
やりたいこと
const htmls = van.state([HTML要素, ...]) htmls.val = [新しいHTML要素, ...]
複数のHTML要素をまとめてリアクティブに更新したいです。
たとえばマークダウンを入力し、それをHTMLにパースして、HTML要素を配列にし、それをリアクティブに更新する場合などを想定しています。
コード
const {div,h1,p} = van.tags const htmls = van.state([h1('van.state()'), p('本文。')]) van.add(document.body, ()=>div(htmls.val)) // OK htmls.val = [h1('van.state()書き換え'), p('本文を書き換えた。')]
ポイントは以下。
van.state([])
を使う(vanX.reactive([])
はダメ)- リアクティブにしたい要素や属性があるときは関数で返す
- 要素配列を
van.add
したいときはdiv
に配列を渡してから返す
See the Pen Untitled by ytyaru (@ytyaru) on CodePen.
失敗例
van.add(document.body, ...htmls.val) // リアクティブでない
van.add(document.body, htmls) // NG [object HTMLHeadingElement],[object HTMLParagraphElement] van.add(document.body, ()=>htmls.val) // NG [object HTMLHeadingElement],[object HTMLParagraphElement]
van.add(document.body, ()=>...htmls.val) // NG SyntaxError: Unexpected token '...'
vanX.reactive()
を使って以下のように書いてもダメでした。
const html2s = vanX.reactive([h1('vanX.reactive()'), p('本文。')]) //van.add(document.body, html2s) // NG [object HTMLHeadingElement][object HTMLParagraphElement] //van.add(document.body, vanX.stateFields(html2s)) // NG [object Object] //van.add(document.body, vanX.stateFields(html2s).val) // NG 何も表示されない //van.add(document.body, vanX.list(div, html2s, (v)=>v)) // NG [object Object][object Object]
返す型が違います。van.state([]).val
は配列を返しますが、vanX.stateFields(vanX.reactive([]))
はオブジェクト型を返します。
van.add()
の第二引数以降には追加したいHTML要素を渡すべきです。HTML要素を含んだ配列やオブジェクトなら展開する必要があります。
vanX.list()
を使えばvanX.reactive([el,...])
でもイケるかと思いましたが、ダメでした。よくわかりません。
van.state()
とvanX.reactive()
の違い
両者ともリアクティブにする状態を生成しますが、その構造が違います。
const htmls = [van.tags.h1('H1'),van.tags.p('P')] const s1 = van.state(htmls) console.log(s1)
{i: Array(2), u: Array(2), l: Array(0), o: Array(0)}
const htmls = [van.tags.h1('H1'),van.tags.p('P')] const r = vanX.reactive(htmls) const s2 = vanX.stateFields(r) console.log(s2)
{ "0": { "i": {}, "u": {}, "l": [], "o": [] }, "1": { "i": {}, "u": {}, "l": [], "o": [] } }
vanX.reactive()
のほうは配列でなくオブジェクトに変換されてしまうようです。配列のインデックス0
,1
がオブジェクトのキーになっています。
変数名がi
,u
,l
,o
など短い一字に変換されています。minifyしたライブラリ*.min.js
を使ったせいです。min
でないライブラリファイルに差し替えると、ちゃんとした名前が見れます。それが以下です。val
, oldVal
はvan.state()
のプロパティとして公式ドキュメントに書いてあったので、それに対応する値でしょう。
{ "_val": [ {}, {} ], "_oldVal": [ {}, {} ], "_bindings": [], "_listeners": [] }
デバッガで見るとわかりますが、値はProxyクラスにされて返却されていました。詳しくは気にしなくて大丈夫でしょう。
結論
VanJSで要素の配列をリアクティブにbody
へ挿入したいときは、次のようにする。
van.state()
を使うdiv()
の引数に要素配列を渡す- 2を
van.add()
に渡す
const {div,h1,p} = van.tags const htmls = van.state([h1('見出し'), p('本文。')]) van.add(document.body, ()=>div(htmls.val)) htmls.val = [h1('見出し書き換え'), p('本文を書き換えた。')]