LoginSignup
3
2

More than 1 year has passed since last update.

VueでHTML既存の<button>をラップするとき全てのpropsを再定義している人いる‥?

Last updated at Posted at 2023-01-06

React(tsx)でよくみる下記の記述

下位レベルのコンポーネント(アトミックデザインで言うatom)を定義するときいちいちpropsを再定義するのは面倒なので、もとの<button>が持っている属性の定義をそのまま使って、受け取ったpropsをそのままスプレッド演算子で再代入する方法。

const MyButton = (props: JSX.IntrinsicElements['button']) => <button {...props} />

※コード補完が効いてるぞ、というスクリーンショット
スクリーンショット 2023-01-06 20.19.28.png

これVueでもできないの?

と思って調べたんですが、下記のように「ButtonHTMLAttributes」など@vueのパッケージに含まれているruntime-dom.d.tsに定義されている型定義使うと同じように、面倒なpropsの再定義を回避することができそうです。

<template>
  <button class="button" v-bind="props"><slot></slot></button>
</template>

<script setup lang="ts">
import { ButtonHTMLAttributes } from 'vue'

interface Props extends ButtonHTMLAttributes {}
const props = defineProps<Props>()
</script>

※コード補完が効いてるぞ、というスクリーンショット
スクリーンショット 2023-01-06 20.21.26.png

ちなみに、空のinterfaceがeslintで勝手にtypeに変換されて、vueのコンパイラに怒られるという人は以下のように@typescript-eslint/no-empty-interfaceをeslintの設定に指定すると回避できました。

これが

interface Props extends ButtonHTMLAttributes {}

これに変換されて怒られる場合は

type Props = ButtonHTMLAttributes

eslintの設定をこう。

.eslintrc.js
/** @type {import("eslint").Linter.Config} */
module.exports = {
  env: {
    browser: true,
    es2021: true
  },
  extends: [
    'plugin:vue/vue3-recommended',
    'eslint:recommended',
    '@vue/typescript/recommended',
    'prettier'
  ],
  parserOptions: {
    ecmaVersion: 12
  },
  plugins: ['vue', '@typescript-eslint'],
  rules: {
    'vue/multi-word-component-names': 'off',

// ここから
    '@typescript-eslint/no-empty-interface': [
      'error',
      {
        allowSingleExtends: true 
      }
    ]
// ここまで
  }
}

検証浅めなので、もっと良い方法あったらコメントで教えて下さい🎍

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2