owned mediaウェブ制作に役立つコンテンツを発信中!

Vue.js(Options API)からReactへの移行でみる違いと比較 #3:テンプレート処理

最終更新日: Update!!
前回に引き続きVue.jsとReactの違いを比較していきたいと思います。今回はテンプレート上での処理についてみていきます。Vue.jsもReactも処理に合わせてDOMを動的に切り替えることが多々あるのですが、その場合には処理の結果やコンポーネント内のステートによってDOMが変わりますので、テンプレート側でも何らかの処理が加える必要があります。また前回までの記事も合わせてご参考ください。 (過去記事) Vue.js(Options API)からReactへの移行でみる違いと比較 #1:コンポーネント Vue.js(Options API)からReactへの移行でみる違いと比較 #2:メソッド・ステート   これまでに引き続きサンプルとしてあげているアプリケーションのコードになります。今回はテンプレート上の処理をメインにしているので、テンプレート部分に関係するところだけを抜粋しています。Vue.jsではよりHTMLに近い形で、独自構文が使われているのが確認できます。対するReactではJSX記法でHTMLの文字列を出力している形になりますね。 【App.vue(Vue.js)】※一部抜粋
<template>
  <h1>TODO List(Vue)</h1>
  <ul class="list">
    <task-item v-for="(task, index) in tasks" :key="`${task}-${index}`" :task-data="{ index, task }" @delete-task="deleteTask" />
  </ul>
  <input v-model="newTask" class="task-input" type="text" placeholder="タスクを入力" />
  <button class="button-add" @click="addTask">追加</button>
  <div v-if="isError" class="error-message">タスクが空欄です</div>
</template>
  【TaskItem.vue(Vue.js)】※一部抜粋
<template>
  <li class="list-item">
    <button class="button-delete" @click="emitDeleteTask(taskData.index)">削除</button>
    <span>{{ taskData.task }}</span>
  </li>
</template>
  【App.jsx(React)】※一部抜粋
return (
  <>
    <h1>TODO List(React)</h1>
    <ul className={AppCSS['list']}>
    {
      tasks.map((task, index) => {
        return <TaskItem 
          taskData={{ index, task }} 
          key={`${task}-${index.toString()}`} 
          methods={
            { deleteTask }
          } 
        />
      })
    }
    </ul>
    <input 
      ref={refs}
      onChange={dataBinding}
      className={AppCSS['task-input']} 
      type="text" 
      placeholder="タスクを入力" 
    />
    <button 
      onClick={() => {
        addTask();
        formReset();
      }}
      className={AppCSS['button-add']}
    >追加</button>
    {
      isError && <div className={AppCSS['error-message']}>タスクが空欄です</div>
    }
  </>
)
  【TaskItem.jsx(React)】※一部抜粋
return (
  <>
    <li className={TaskItemCSS['list-item']}>
      <button 
        onClick={() => props.methods.deleteTask(props.taskData.index)} 
        className={TaskItemCSS['button-delete']}
      >削除</button>
      <span>{props.taskData.task}</span>
    </li>
  </>
)
  では上記のコードでも記述されている、コンポーネントのテンプレート上で行われる処理の部分を比較していきます。    
1. 変数展開(テンプレートリテラル)
処理の中で使われる、ステートなどの変数や、算出プロパティはテンプレート上に値として出力することができます。Vue.jsではマスタッシュ記法と呼ばれ、波括弧を二重にして囲み、その中で変数名や関数名を記述します。
// Vue.js(Options API)
<template>
  <div>{{ variableName }}</div>
</template>
  Reactでも同じ要領でテンプレート上に変数を展開できます。ただ二重ではなく波括弧は1つだけになります。また、波括弧の中では変数だけではなくJavaScriptの処理が書けるようになります。
// React
return (
  <>
    <div>{ variableName }</div>
  </>
)
   
2. v-if(条件付きレンダリング)
HTMLを特定の条件の時に出力したい、切り分けたいなどの時に、Vue.jsでは「v-if」という独自のディレクティブを使うことで簡単に条件分岐ができるようになります。HTMLの属性のように扱われ、条件式をそのまま入力します。
// Vue.js(Options API)
<template>
  <div>
    <p v-if="isError">エラーがあります</p>
    <p v-else>正しく入力されています</p>
  </div>
</template>
  Reactではそのような独自構文が存在しないため、単純にif文や三項演算子などで条件分岐を行う必要がありますが、このように「&&」の論理演算子を使うとシンプルに記述ができます。
// React
return (
  <>
    { isError && (<p>エラーがあります</p>) }
    { !isError && (<p>正しく入力されています</p>) }
  </>
)
   
3. v-for(リストレンダリング)
配列やオブジェクトに合わせて、HTMLを繰り返し出力したいこともよくあります。そんな場合にはVue.jsでは「v-for」のディレクティブを使ってループさせることができます。ループの中では配列の値やオプジェクトのキーを指定することで呼び出した値をHTML上に出力することができます。その際にはkey属性でユニークな値を割り振っておく必要があります。
// Vue.js(Options API)
<template>
  <ul>
    <li v-for="(item, index) in items" :key="item.id">{{ item.name }}</li>
  </ul>
</template>
  Reactでは自前で繰り返し処理をする必要があります。配列をmap()メソッドでHTMLの値としてループで出力していきます。配列やオブジェクトの値の展開や、key属性の指定などはVue.jsと同様になりますね。
// React
return (
  <>
    <ul>
    {
      items.map((item, index) => {
        return <li key={ item.id }>{ item.name }</li>
      })
    }
    </ul>
  </>
)
   
4. v-html(HTML文字列の挿入)
変数として扱われる動的なHTMLの文字列の出力をしたい時には、Vue.jsでは「v-html」というのが使われます。
// Vue.js(Options API)
<template>
  <div v-html="htmlStrings"></div>
</template>
  Reactの場合ですと「dangerouslySetInnerHTML」属性を使います。ただ「__html」のキーがついたオブジェクトの形で指定する点だけ注意します。
// React
return (
  <>
    <div dangerouslySetInnerHTML="{{ __html: htmlStrings }}"></div>
  </>
)
   
5. ref(DOM参照)
テンプレート内の要素をDOMとして操作したい場合には「ref」属性を指定することで、処理側では「$refs」の中でDOMを呼び出すことができます。
// Vue.js(Options API)
<template>
  <input type="text" value="defaultValue" ref="formInput" />
</template>

<script>
  export default {
    mounted() {
      console.log(this.$refs.formInput.value);
    }
  }
</script>
  Reactでは「useRef」フックを使うことで同様のことが実現できます。「current」キーを指定することで指定したDOMを参照することができます。
// React
import React, { useEffect, useRef } from 'react';
export const App = () => {
  const refs = useRef(null);
  useEffect(() => {
    console.log(refs.current.value);
  }, [])
  return (
    <>
      <input type="text" value="defaultValue" ref={refs} />
    </>
  )
}
  テンプレート内の処理を行う場合には、Vue.jsでは独自の構文が用意されているのに対して、Reactでは自前で処理を書いていく必要があります。Vue.jsで独自構文を覚える学習コストはあるものの、記述は楽になりますが、ReactではVanillaJSに近い形で書けるのでJavaScriptに慣れている方ですとこちらの方が自然に見えるのかもしれませんね。
  • はてなブックマーク
  • Pocket
  • Linkedin
  • Feedly

この記事を書いた人

Twitter

sponserd

    keyword search

    recent posts

    • Twitter
    • Github
    contact usscroll to top
      • Facebook
      • Twitter
      • Github
      • Instagram