Search code examples
javascriptreactjsvue.js

How to implement reusable component input in vue 3?


could anyone can give me a hint about reusable component input in vue 3? Like this in React:

Let say,

  1. use <Input /> reusable component in parent component
import { useState } from 'react';
import Input from './component/Input';

function Home() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    
    console.log(email, password);
  }

  return (
    <form onSubmit={handleSubmit}>
      <Input id="email" labelText="Email" value={email} onChange={e => setEmail(e.target.value)} />
      <Input id="password" labelText="Password" value={password} onChange={e => setPassword(e.target.value)} />
      <button type="submit">Login</button>
    </form>
  );
}
  1. here <Input /> component:
export default function Input(props) {
  const { id, labelText, value, onChange } = props;

  return (
    <label htmlFor={id}>{labelText}<label>
    <input id={id} value={value} onChange={onChange}>
  );
}

Solution

  • You should read up on Component Basics from the Vue 3 docs.

    Key concepts:

    • Use the v-bind directive (or : prefix for shorthand) for data binding
    • Use the v-on directive (or @ prefix for shorthand) for event handlers
    • Use double curly brackets for string interpolation of data properties
    • Use the v-model directive for two-way data binding
    • Use props option to declare properties
    • Use ref to create data properties using Composition API

    The equivalent input component in Vue 3:

    <template>
      <label :for="id">{{ labelText }}</label>
      <input
        :value="modelValue"
        @change="$emit('update:modelValue', $event.target.value)"
        :id="id"
      />
    </template>
    
    <script>
    export default {
      props: {
        id: String,
        labelText: String,
        modelValue: String,
      },
    };
    </script>
    

    And the form:

    <template>
      <form @submit="handleSubmit">
        <MyInput id="email" labelText="Email" v-model="email" />
        <MyInput id="password" labelText="Password" v-model="password" />
        <button type="submit">Login</button>
      </form>
    </template>
    
    <script>
    import MyInput from "@/components/MyInput.vue";
    import { ref } from "vue";
    
    export default {
      components: {
        MyInput,
      },
      setup() {
        const email = ref("");
        const password = ref("");
    
        return {
          email,
          password,
          handleSubmit(e) {
            e.preventDefault()
            console.log("submit", email.value, password.value);
          },
        };
      },
    };
    </script>
    

    demo