How to use props in <script setup> in vue3
Asked Answered
J

8

104

Just like the title says, related Links: New script setup (without ref sugar)

<template>
  <TopNavbar title="room" />
  <div>
    {{ no }}
  </div>
</template>

<script setup>
import TopNavbar from '@/layout/TopNavbar.vue'
import { defineProps, reactive } from 'vue'

defineProps({
  no: String
})

const state = reactive({
  room: {}
})

const init = async () => {
  // I want use props in this
  // const { data } = await getRoomByNo(props.no)
  // console.log(data);
}
init()

</script>

<style>
</style>
Jorgejorgensen answered 26/2, 2021 at 8:16 Comment(0)
C
122

To use props with <script setup> you need to call defineProps() with the component prop options as the argument, this defines the props on the component instance and returns a reactive object with the props which you can use as follows:

<template>
  <TopNavbar title="room" />
  <div>
    {{ no }}
  </div>
</template>

<script setup>
import TopNavbar from "@/layout/TopNavbar.vue";
import { defineProps, reactive } from "vue";

const props = defineProps({
  no: String,
});

const { no } = toRefs(props);

const state = reactive({
  room: {},
});

const init = async () => {
  const { data } = await getRoomByNo(no.value);
  console.log(data);
};

init();
</script>

If you are using typescript the alternative way to do this is pass a type only declaration and infer the prop types from that. Pro's are that you'll get stricter type safety but you cannot have default values.

<template>
  <TopNavbar title="room" />
  <div>
    {{ no }}
  </div>
</template>

<script setup>
import TopNavbar from "@/layout/TopNavbar.vue";
import { defineProps, reactive } from "vue";

const props = defineProps<{
  no: string,
}>();

const { no } = toRefs(props);

const state = reactive({
  room: {},
});

const init = async () => {
  const { data } = await getRoomByNo(no.value);
  console.log(data);
};

init();
</script>

EDIT

Defaults with type only props are now possible:

interface Props {
  msg?: string
}

const props = withDefaults(defineProps<Props>(), {
  msg: 'hello'
})
Captain answered 17/3, 2021 at 19:56 Comment(2)
FYI: I also needed to import 'toRefs' from vueEnterostomy
Note that toRefs is only needed if you want to destructure (or "split") props to pass a single prop to a composition function as ref for example. In other cases, just use props.propName directlyBrattice
S
25

Very simple answer using features from Vue-3.1 and later:

CircleImage.vue

<template>
  <div class="px-4 w-8/12 sm:w-3/12">
    <img :src="src" :alt="alt" class="border-none rounded-full h-auto max-w-full align-middle" />
  </div>
</template>

<script setup>
const props = defineProps({
  src: String,
  alt: String,
})
</script>

MyView.vue

<template>
  <div class="flex flex-wrap justify-center">
    <CircleImage src="/file1.jpg" alt="one" />
    <CircleImage src="/file2.svg" alt="two" />
  </div>
</template>

<script setup>
import CircleImage from '@/components/CircleImage.vue'
</script>

See also the documentation: Declaring props or additional options

Strappado answered 16/7, 2021 at 9:15 Comment(1)
I've edited your answer based on this question: https://mcmap.net/q/211663/-what-does-a-quot-view-quot-extension-mean-in-vue/8816585 .view is probably a typo and should be .vue rather. Please correct me if it's wrong.Brunelleschi
J
8

I read "Newscript setup" and found the answer

first,use variable save defineProps

const props = defineProps({
  no: String
})

then use it

const init = async () => {
  console.log(props.no);
}

this is all code:

<template>
  <TopNavbar title="room" />
  <div>
    {{ no }}
  </div>
</template>

<script setup>
import TopNavbar from '@/layout/TopNavbar.vue'
import { defineProps, reactive, useContext } from 'vue'

const props = defineProps({
  no: String
})

const state = reactive({
  room: {}
})

const init = async () => {
  console.log(props.no);
}
init()

</script>

<style>
</style>
Jorgejorgensen answered 26/2, 2021 at 8:32 Comment(0)
H
7

No need to call explicitly withDefaults

<script setup>
import { defineProps } from 'vue'

defineProps({
  isOpen: {
    type: Boolean,
    default: true
  }
})
</script>
Harbison answered 30/12, 2021 at 12:3 Comment(2)
Got any official reference for that one?Brunelleschi
I was trying with withDefaults and my Props were not working. Thanks for your solution. 👍Tappet
U
4

Edit: This answer is outdated. The RFC was changed to use defineProps(..), which is auto-imported if using SFCs.

As per the ongoing RFC, the setup tag can have a string following where you can define which context you wish to have, like so:

<script setup="props, { emit }">
import { watchEffect } from 'vue';

watchEffect(() => console.log(props.msg));
emit('foo');
</script>

These are the same arguments that the setup() method receives.

Unassuming answered 26/3, 2021 at 15:1 Comment(1)
That RFC is from a stale branch and was superseded: PR - github.com/vuejs/rfcs/pull/227 Rendered - github.com/vuejs/rfcs/blob/master/active-rfcs/…Captain
H
2

if you need your props to be reactive you can get them in your child component like this:

const props = defineProps({
    no: String,
    myIdOfSomething: Number
})

const { no, myIdOfSomething } = toRefs(props);

console.log(no.value)
console.log(myIdOfSomething.value)

source https://vuejs.org/api/sfc-script-setup.html#defineprops-defineemits

Happygolucky answered 6/12, 2022 at 20:41 Comment(0)
G
1

Using Typescript you could define your props in two syntaxes :

  1. First syntax

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

const props=defineProps({
   color:{
      type:String as PropType<'primary'|'info'|'success'|'error'|'warning'>,
      default :'primary'
    }
})

</script>

  1. Second syntax

<script setup lang="ts">

type Color='primary'|'info'|'success'|'error'|'warning'

const props=defineProps<{color:Color}>()

</script>

This syntax supports only :

  • A type literal
  • A reference to an interface or a type literal in the same file
Glanders answered 4/6, 2022 at 9:36 Comment(0)
A
0

If you're using Typescript and also want to add a default value, you can use this syntax.

<script setup lang="ts">

interface Props {
 disabled: boolean;
 loading: boolean;
 bordered: boolean;
 label?: string;
}

const props = withDefaults(defineProps<Props>(), {
 label: "Button Label",
}); 
</script>
Almire answered 24/7, 2022 at 10:44 Comment(3)
Is there a way to do this if your are not using Typescript?Deckle
The code sample has the props inverted - label is required and can't have a default value, unlike disabled, loading and bordered that require it.Canova
That's correct. Thanks for you feedback. I'll update it.Almire

© 2022 - 2024 — McMap. All rights reserved.