【问题标题】:vue ref on custom child component not working自定义子组件上的 vue ref 不起作用
【发布时间】:2020-10-06 18:39:37
【问题描述】:

我已经搜索了几个小时,阅读了无数 vue 文档和 stackoverflow 上的相关帖子,但没有运气。

我需要访问组件的内部属性,因为该组件只不过是我需要在父组件中访问的 vanilla 组件的包装器。

我正在尝试创建一个唯一且只能在父 (App) 组件内部访问的 ref,我的理解是我应该在 setup 方法中执行此操作,如下所示:const myRef = ref(null)

但是,唉,myRef.value 永远是null

??????????

codesandbox demo

入口文件:

import { createApp } from 'vue'
import App from "./App.vue";

createApp(App).mount('#app')

家长App.vue:

<template>
    <Foo ref="myRef"/>
</template>

<script>
import { onMounted, ref } from 'vue'
import Foo from "./components/Foo.vue"

export default {
  name: "App",
  components: { Foo },

  setup(props) {
    const myRef = ref(null)

    onMounted(()=>{
      console.log(111,  myRef.value)
    })

    return {
      myRef
    }
  }
}
</script>

子组件Foo.vue:

<template>
  <div>xxx</div>
</template>

<script>
export default {
  name: "Foo",
  mounted() {
    this.test = 123
  }
}
</script>

如果我将ref="myRef" 放在&lt;h1&gt; 上,它可以工作,但我需要它在我的自定义组件上工作,这样我才能访问那里的东西...

现在我不知道关于 vue 的 jack****,而且那里有大量相互矛盾的令人困惑的信息。我在我的演示中使用版本 v3 和 @ 987654335@ 组件是以这种方式创作的(从我从那里的精神错乱中我几乎无法理解),但我的组件 tagify.vue 是以v2 的方式创作的 - 供更广泛的受众使用。


更新 - 经过大量浪费时间

这是 codesandbox 控制台错误!它错误地显示为null 我太信任他们的控制台,所以不打开浏览器的控制台(由于性能原因,因为它大大降低了我在该特定网站上的计算机速度)。

【问题讨论】:

  • 它应该是this.$refs.myRef(至少在 Vue.js 2.x 中)。恕我直言,混合 Vue.js 2.x 和 3.x 并不是一个好主意。
  • @FedericoMoretti - 考虑 tags 一个从 npm 导入的 vue2 组件。这是一个完全正常的情况。请注意,父代码中没有this 这样的东西。是 vue3 的新 API

标签: javascript vue.js vuejs2 vuejs3


【解决方案1】:

至于父组件 我认为主要问题是目前在 Vue 2.x 上,您不能在 Vue 组件的模板中放置 2 个直接子元素。 *** 你实际上可以,但前提是你将使用 JSX 渲染函数而不是 &lt;template&gt;&lt;/template&gt; 块。

其次,你不应该在模板中使用x.value,而只能使用x(它在vue-loader内部处理)。所以,将:value="tagifyStuff.value" 替换为:value="tagifyStuff"

冷成分 v-model 不适用于props.value,因为来自的数据不能被变异。

在 props 中传递函数以进行操作,例如“onClick”,这不是“vue 方式”。 你的组件应该使用 $emit() 方法来分发一个事件,并且父组件应该使用@my-event="doWhatever"订阅这个事件

最好使用 &lt;style&gt; 标签中的 CSS。 如果您坚持使用单独的文件,也可以写&lt;style src="@yaireo/tagify/dist/tagify.css"/&gt;

顺便说一句,如果你想使用父级的 Tagify 实例,你为什么不直接发出它? 你可以写:

mounted() {
    this.tagify = new Tagify(this.$el, this.settings);
    this.$emit('ready', this.tagify);
}

然后像这样在父级中使用它:

<template><my-child @ready="tagifyIsReady"/></template>
<script>
export default {
  setup() {
    let tagify;
    return: {
      tagifyIsReady: (tagifyInstance) => tagify = tagifyInstance
    }
  }
}
</script>

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,并在 Vue Discord 服务器上解决了它。这就是你在 Vue 3 中使用组合 API 的方式:

    App.vue:

    <template>
      <v-header @get-started="scrollToTable" />
      <v-table ref="tableRef" />
    </template>
    
    <script setup>
    import VTable from "./components/Table.vue";
    
    import { ref } from "vue";
    
    const tableRef = ref(null);
    
    const scrollToTable = () => {
      tableRef.value.getRef()?.scrollIntoView({ behavior: "smooth" });
    };
    </script>
    
    

    Table.vue:

    <template>
      <table ref="root">
        <!-- some stuff here -->
      </table>
    </template>
    
    <script>
    import { ref } from "vue";
    
    export default {
      setup() {
        const root = ref(null);
        const getRef = () => root.value;
    
        return { root, getRef };
      },
    };
    </script>
    

    【讨论】:

    • 但我说它与 Vue 无关,它是 codesandbox 本身(他们正在使用的控制台组件)中的一个错误
    • 我真的只能与 OP 中的示例相关。这不适用于组件:v3.vuejs.org/guide/…,因此是我的答案。
    • 我是 OP... 我在问题中写道,整个问题是代码和框中的错误。 Vue 代码本身没有错误
    【解决方案3】:

    <template>
        <Foo ref="myRef"/>
    </template>
    
    <script>
    import { ref, watch } from 'vue'
    import Foo from "./components/Foo.vue"
    
    export default {
      name: "App",
      components: { Foo },
    
      setup(props) {
        const myRef = ref(null)
        
        watch(myRef, newValue => {
           console.log(111,  newValue)
        })
        
        return {
          myRef
        }
      }
    }
    </script>

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 2022-12-15
    • 1970-01-01
    • 2020-01-09
    • 1970-01-01
    • 2020-08-07
    • 1970-01-01
    • 1970-01-01
    • 2021-06-24
    • 2020-01-30
    相关资源
    最近更新 更多