105

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>

8 Answers 8

127

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'
})
Sign up to request clarification or add additional context in comments.

2 Comments

FYI: I also needed to import 'toRefs' from vue
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 directly
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

1 Comment

I've edited your answer based on this question: stackoverflow.com/q/74534343/8816585 .view is probably a typo and should be .vue rather. Please correct me if it's wrong.
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>

Comments

7

No need to call explicitly withDefaults

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

defineProps({
  isOpen: {
    type: Boolean,
    default: true
  }
})
</script>

2 Comments

Got any official reference for that one?
I was trying with withDefaults and my Props were not working. Thanks for your solution. 👍
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.

1 Comment

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/…
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

Comments

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

Comments

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>

3 Comments

Is there a way to do this if your are not using Typescript?
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.
That's correct. Thanks for you feedback. I'll update it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.