Search code examples
vuejs3vue-composition-apivue-script-setup

vuejs3: how to init a ref using a prop?


I have this codes

<script setup>

defineProps({
  position: { type: String, required: false, default: "center middle" },
});

</scritp>

I am trying adding this after defineProps

const myPosition = ref(position);

But I got

Uncaught (in promise) ReferenceError: position is not defined

What am I doing wrong, and, important, why?


Solution

  • To initialize a prop using the "Component" API along with <script setup>, you will want to assign the object returned by the defineProps(...) macro a name, say props and use that variable name when referring to the props in your script. So if you have a prop declared like so:

    const props = defineProps({
      position: { type: String, required: false, default: "center middle" },
    });
    

    You can use it in the same script like so:

    const myLocation = ref(props.position);
    

    So, a complete example could look like so:

    enter image description here

    ParentComponent.vue

    <template>
      <div class="main-body">
        <h1>Parent Component</h1>
    
        <div class="grid-container">
          <div>
            Position (in Parent):       
          </div>
          <div>
            <input v-model="msg">
          </div>
        </div>
        <hr>
        <div>
            <Child :position="msg" title="Child Component 1"/>
        </div>
        <div>
            <Child  title="Child Component 2 (default position property)"/>
        </div>
      </div>
    </template>
    
    <script setup>
    import { ref } from 'vue'
    import Child from './Child.vue'
    
    const msg = ref('North West')
    </script>
    
    <style>
      .main-body {
        margin: 10px 20px;
      }
      .grid-container {
        display: grid;
        grid-template-columns: 1fr 2fr;
      }
    </style>
    

    and then

    Child.vue

    <template>
        <h2>
        {{ title }}
      </h2>
      <div class="grid-container">
        <div>
          Position (from parent): 
        </div>
        <div>
          {{ position }}
        </div>
        <div>
          My Position: 
        </div>
        <div>
          <input type="text" v-model="myLocation">
        </div>
        <div>
          My Position: 
        </div>
        <div>
          {{ myLocation }}
        </div>
      </div>
      
    </template>
    
    <script setup>
    import { ref } from 'vue';
    
    const props = defineProps({
      position: { type: String, required: false, default: "center middle" },
      title: { type: String, required: false, default: "ChildComponent"}
    });
    const myLocation = ref(props.position);  
    </script>
    
    <style scoped>
      .grid-container {
        display: grid;
        grid-template-columns: 1fr 2fr;
      }
    </style>
    

    Also, please check out this code in the Vue Playground

    In this example, the myPosition field is initialized with the prop, but then once the application has been launched, this field is no longer dependent on the prop.