VueはtemplateプロパティにHTMLを書き、それにディレクティブを書くというスタイルで作っていきます。
new Vue({
el: "#app",
template: "<div>{{ text }}</div>",
data: function(){
return {
text: "hello world"
}
}
})
▲普通にtemplateを使用したとき
これでも十分目的を果たせるのですが、 text
に入れる文書にURLが入っており、それだけaタグにしたいというちょっと凝った要求は実現しにくいです。
そういった凝った要求には、Vueの2系列で使えるようになった render
関数を使うことで、テキストをパースして動的にHTMLをくみ上げていくということで満たすことが出来ます。
new Vue({
el: "#app",
render: function(createElement){
return createElement("div", [this.text])
},
data: function(){
return {
text: "hello world"
}
}
});
▲ render
を使用したとき
ですが、render
関数を普通に使おうとすると引数として渡されてくる createElement
でHTMLをくみ上げていくことになるので、HTMLを普通にくみ上げていくのに慣れている身としては少し使いづらい感じがします。
そこで、Vueでは render
関数にJSXを使うことが出来るので、それを利用してHTMLを組むのに近い感覚で凝った要求を満たそうと思います。
パッケージのインストールとJSXの使用
まずJSXを使用するには babel-plugin-syntax-jsx
babel-plugin-transform-vue-jsx
babel-helper-vue-jsx-merge-props
をインストールします。これをインストールすると render
内でJSXを書くことが出来るようになります。
上の例をJSXで書くと以下のようになります。
new Vue({
el: '#app',
render (h) {
return <div>
{ this.text }
</div>
},
data: function(){
return {
text: "hello world"
}
}
});
▲ render
でJSXを使ったとき
テキスト中のURLをaタグにする
JSXで書けるようになったので、テキスト中のURLをaタグにする処理を書いてみます。少し無理矢理感が否めませんが以下のように書きました。
const regex = /http(:\/\/[-_.!~*¥'()a-zA-Z0-9;\/?:¥@&=+¥$,%#]+)/
new Vue({
el: '#app',
render (h) {
let processTextArray = this.parseText();
return <div>
{ processTextArray.map((text) => {
if(text.match(regex)) {
return <a href={text}>{text}</a>
} else {
return text
}
})}
</div>
},
data: function(){
return {
text: "hello world http://www.google.com/ http://www.facebook.com/"
}
},
methods: {
parseText: function(){
let processText = this.text
let match
let matchObj = {}
let count = 0
while ((match = regex.exec(processText)) != null) {
count += 1
matchObj[`[${count}]`] = match[0]
processText = processText.replace(match[0], `[${count}]`)
console.log(processText)
}
const keys = Object.keys(matchObj)
keys.forEach((key) => {
processText = processText.replace(key, `,${matchObj[key]},`)
})
return processText.split(',')
}
}
});
▲ テキストを処理するメソッドを用意する
テキストを処理するメソッドを用意し、そこから得られた文字列の配列がURLだったときaタグにするようにしています。
メソッドの処理としては簡単にURLがマッチしたら [1]
のような特定できる適当な文字列で置き換え、置き換えたものを再度 ,
をつけたURLで置き換え、最後に ,
で分割しています。
多分もっと良いやり方があると思うのですが、いったんこれで目的を達することが出来ました。
まとめ
以上、VueでJSXを使い、DOMを構築してみました。createElement
を使ったやり方よりもわかりやすくDOMを構築できたと思います。URLをパースする方法はもうちょっと良い方法がある気がしますが、これは今後の課題にしておきます。