vuejs/rfcs

Setup sugar cannot pass the ref to the ref function param.But I can get the ref object correctly with no sugar

recovery-alt opened this issue · 17 comments

When I use ref function in the parent component and ref string in the children, setup sugar cannot get the refs correctly.Here is my code, or you can view my repo.

App.vue

<template>
  <HelloWorld :ref="setRef" />
</template>
<script lang="ts">
export default {
  setup() {
    const setRef = el => {
      // el is an empty object
      console.log(el); 
    };
    return { setRef };
  }
};
</script>

HelloWorld.vue

<template>
  <div ref="dom">demo</div>
</template>

<script lang="ts" setup>
const dom = ref();
</script>

I think you just need to do

import { onMounted } from 'vue'

onMounted(() => {
  console.log(dom)
})

In the second one, and you will have your ref? Isn't this just a race condition, where the ref is not initialized until the component is rendered? The first example you call the function, which is only called when the DOM element exists. In the second one, this is not the case. I don't think the two snippets are equivalent.

In general I think you always want to do template ref things inside of onMounted, to ensure the elements they refer to exist.

See this example: https://v3.vuejs.org/guide/composition-api-template-refs.html#template-refs

Also, I should have been more clear, I think this issue should be in vue-next, where the actual code for <script setup> lives. This RFC repo is just for ideas/discussions, not actual bugs.

Thanks for your apply. I will go to the vue-next.

Did my suggestion work?

I've tried. It doesn't work.

I just tried and it works fine for me. I did not try your repo yet. I suspect there is no bug, though, I'd have to look more closely and try your code. Maybe this working snippet helps:

<template>
  <img ref="theRef" alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld msg="Hello Vue 3 + Vite" />
</template>

<script setup>
import { onMounted, ref } from 'vue'

const theRef = ref(null)

onMounted(() => {
  console.log(theRef.value)
})

import HelloWorld from './components/HelloWorld.vue'
</script>

image

I think you mistake my problem. I'd like to get the children ref in the parent component using ref function. Then the dom object will pass to the first param of this function setRef . While I use sugar in the children component and set the root element ref="dom", I cannot get the fisrt param correctly in the context setRef.

const setRef = el => {
  // el is an empty object
  console.log(el); 
};
posva commented

Don't duplicate issues, thanks.

Don't duplicate issues, thanks.

So, what's the solution? I had a similar problem, but I couldn't find the original problem.

I think you mistake my problem. I'd like to get the children ref in the parent component using ref function. Then the dom object will pass to the first param of this function setRef . While I use sugar in the children component and set the root element ref="dom", I cannot get the fisrt param correctly in the context setRef.

const setRef = el => {
  // el is an empty object
  console.log(el); 
};

How did you finally solve it?

In my case, ref can get value on html tag but get empty object on custom component tag which also use <script setup>.

// NotOk.vue
<template>
   i'm not ok
</template>

<script setup>
</scritp>
// App.vue
<template>
   <div ref="ok">I'm OK </div>
   <not-ok ref="notok"></not-ok>
</template>

<script setup>
    import NotOk from '../components/NotOk.vue'
    
    import { ref , onMounted } from 'vue'

    const ok = ref(null)
    const notok = ref(null)

    onMounted(() => {
        console.log(ok)  //  {..., value: Proxy(), ...}
        console.log(notok)  // empty object
    })
</scritp>

same problem as @lanbin

@Abunuo Give up the sugar, then you can sovle it.

@Abunuo Give up the sugar, then you can sovle it.

Thank you. That's what I did.

same problem as @lanbin

this really is a bug ,it should not be closed

Why is this closed? Where is the original issue if this is a duplicate? I am having the same Problem 🤔

script setup components are closed by default, they do not expose their state to the parent on the ref instance. The components have to explicitly expose state to the outside world.

See: https://vuejs.org/api/sfc-script-setup.html#defineexpose

However, public APIs like $el are still accessible no matter what.

See this playground