Home > other >  How to pass refs from parent component to child component? Without using Typescript?
How to pass refs from parent component to child component? Without using Typescript?

Time:01-23

I have an App.vue with the property "clicked" that I'm trying to pass to child components.

App.vue

<template>
  <NavBar :clicked="clicked"/>
  <BackDrop :clicked="clicked"/>
  <SideDrawer :clicked="clicked" />
  <router-view></router-view>
</template>
<script>
import { ref } from "vue";
import NavBar from "./components/Navbar/NavBar.vue";
import BackDrop from "./components/Backdrop/BackDrop.vue";
import SideDrawer from "./components/Sidedrawer/SideDrawer.vue";
export default {
  name: "App",
  components: { NavBar, BackDrop, SideDrawer },

  setup() {
    const clicked = ref(false);

    return { clicked };
  },
};
</script>
export default App;

so the child components can be rendered conditionally like:

SideDrawer.vue

<template v-if="clicked">
  <div ></div>
</template>
<script setup>
</script>

Did I pass the "clicked" ref properly in the "App.vue"?

If I did, how do you access them in the child component? I've already googled and looked at a bunch of StackOverflow posts but the majority of them seem to use, "defineProps()", like this code:

const props = defineProps({
  msg: String,
  user: Object,
});

// Destructuring props
let { name, lastname } = props.user;
</script>

but I'm not using Typescript so this won't work for me.

What is the "non-typescript" way of passing props? Do you need to use Typescript to pass props?


EDIT:

Even when I implement Typescript and use this code:

SideDraw.vue

<template v-if="clicked">
  <div >
    <h1>{{ props.clicked }}</h1>
  </div>
</template>
<script setup>
const props = defineProps({
  clicked: boolean,
});
</script>

I get the errors:

'defineProps' is not defined.eslintno-undef
'boolean' is not defined.eslintno-undef

...

I gathered from this Github thread to set global variables so I did this, but it still doesn't work.

babel.config.js

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
    globals: {
      defineProps,
      defineEmits,
      defineExpose,
      withDefaults
    }
  }
}

CodePudding user response:

In JavaScript you have two common ways of defining props, either with just array of prop names like so:

const props = defineProps([ 'clicked', 'someOtherProp' ]);

Or much more preferred(due to saving between hours and days of troubleshooting) is to define each prop with object as so:

  const props = defineProps({
    clicked: { type: Boolean, default: false, required: true },
  });

Here is the relevant section of docs: https://vuejs.org/guide/components/props.html#prop-validation

CodePudding user response:

No, you do not need TypeScript when defining props. TypeScript is a superset of JavaScript so any TypeScript is also valid JavaScript.

When using <script setup>, you use defineProps to define which props a component can accept. You do not need to declare or import it anywhere as it is a compiler macro. If ESlint is complaining, then it is not configured properly. Add the following to your eslint configuration file.

module.exports = {
    env: {
        'vue/setup-compiler-macros': true
    }
}

In each of your child components you need to accept "clicked" as a property.

<script setup>
const props = defineProps(['clicked'])
</script>

or (using runtime types - this is not Typescript as pointed out by @Estus);

<script setup>
const props = defineProps({
  clicked: Boolean
})
</script>

In your App.vue, you need to pass a value to the prop as follows;

<script setup>
import { ref } from "vue";

const clicked = ref(false);
</script>
<template>
    <NavBar :clicked="clicked"/>
    <BackDrop :clicked="clicked"/>
    <SideDrawer :clicked="clicked" />
    <router-view></router-view>
</template>

If you are not going to use <script setup>, then you can define which props to accept as follows;

export default {
  name: "NavBar",
  props: ['clicked']
};

or (using runtime types - this is not Typescript as pointed out by @Estus);

export default {
  name: "NavBar",
  props: {
    clicked: Boolean
  }
};
  • Related