2020-09-15に更新

ReactコンポーネントをVue.jsみたいに素のHTMLに配置する

ReactコンポーネントをVue.jsのように、コンポーネント名のタグで呼び出す小ネタです。具体的には下記のようにするとコンポーネントの実行結果が表示されるようになります。

<my-component moji="aiu" :obuje="{a: 'a', b: 'b'}"></my-component>

やり方としては下記のようなコードを利用します。anyは手抜きです。単に指定したタグ名を探して、見つかった場合はその属性を取得してコンポーネントのプロパティとして渡してrenderしているだけです。

import React from 'react'
import { render } from 'react-dom'

type Components = {
  [domId: string]: any
}

function getPropertyName(originalName: string) {
  let property = ''
  for (let i = 0; i < originalName.length; i++) {
    const c = originalName.charAt(i)
    if (c === '-') {
      i++
      property += originalName.charAt(i).toUpperCase()
    } else {
      property += c
    }
  }
  return property
}

export function startComponents(components: Components) {
  for (const id in components) {
    const component = components[id]

    const targets = document.querySelectorAll(id)
    targets.forEach(target => {
      const props: { [key: string]: any } = {}
      if (target.hasAttributes()) {
        target.attributes
        for (let i = 0; i < target.attributes.length; i++) {
          const attribute = target.attributes[i]
          if (attribute.name.charAt(0) === ':') {
            props[getPropertyName(attribute.name.substring(1))] = JSON.parse(
              attribute.value
            )
          } else {
            props[getPropertyName(attribute.name)] = attribute.value
          }
        }
      }

      render(React.createElement(component, props), target)
    })
  }
}

ここのコツとして、属性は大文字小文字が関係ないようなので、キャメルケースのプロパティ名を使いたい時はこれもVue.jsと同様にハイフンを利用します。そのための変換処理も入れています。

<my-component :my-property="{a: 'a', b: 'b'}"></my-component>

例えばさっきのコンポーネントを使う場合は下記のように初期化します。

import MyComponent from './components/MyComponent'

startComponents({
  'my-component': MyComponent
})

これでHTML上に簡単にReactコンポーネントを表示できるようになりました。まあガッツリちゃんとやろうと思うと支障が出てくる箇所も出てくる可能性はありますので、あくまでもちょっとした手抜き対応です。

ツイッターでシェア
みんなに共有、忘れないようにメモ

だら@Crieit開発者

Crieitの開発者です。 Webエンジニアです(在宅)。大体10年ちょい。 記事でわかりにくいところがあればDMで質問していただくか、案件発注してください。 業務依頼、同業種の方からのコンタクトなどお気軽にご連絡ください。 業務経験有:PHP, MySQL, Laravel, React, Flutter, Vue.js, Node, RoR 趣味:Elixir, Phoenix, Nuxt, Express, GCP, AWS等色々 PHPフレームワークちいたんの作者

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント