以编程方式添加的引用不适用

时间:2019-07-06 16:08:12

标签: javascript vue.js

我想将ref属性附加到具有自定义指令的HTML元素上。

假设我有一个名为v-custom的指令,并且每当在元素上使用它时,我都希望将ref="elem"添加到元素中。

我尝试使用类似这样的指令:

Vue.directive('custom', {
    inserted(el) {
        el.setAttribute("ref", "elem");
    }
});

在我的组件之一中,我有这个:

<span v-custom>Testing</span>

当我在网页中查看它时,我可以检查该span元素并看到它具有ref属性,但是当我检查它所属的组件的ref时,它表示它不包含“ elem” ref。 / p>

但是,如果我自己添加ref标签,就像这样:

<span v-custom ref="elem">Testing</span>

然后按预期工作,我可以在控制台中看到“ elem”参考。

有什么办法可以使我的用例工作,或者这是预期的行为?

1 个答案:

答案 0 :(得分:1)

正如@skirtle所指出的,ref在vue模板代码中被编写为普通的DOM属性,但是在解析时的处理方式有所不同。 Vue组件实例/视图模型/“ vm”具有对象vm.$refs,该对象将键映射到DOM元素。我们可以自己修改该对象。然后的问题是如何从指令中获取父项vm(我们已经获得了DOM元素el)。

查看自定义指令https://vuejs.org/v2/guide/custom-directive.html#Directive-Hook-Arguments的文档,我们可以看到第三个参数是“ vnode”引用,而查看其文档,我们可以看到vnode.context引用了容器vm;因此:

Vue.directive('my-directive', {
    inserted (el, binding, vnode) {
        console.log('directive inserted')
        const refKey = "s2"
        vnode.context.$refs[refKey] = el // set it
    }
})

Vue.component('my-component', {
    template: '#my-component-template',
    replace: false,
    props: {text: String},
    mounted () {
        console.log('component mounted')
        this.$refs.s1.innerText = 's1 ref working'
        this.$refs.s2.innerText = 's2 ref working' // use it
    }
});

new Vue({
    el: '#app',
    data: {
        status: "initialized",
    },
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
    hello
    <my-component :text="status"></my-component>
</div>

<script type="text/x-template" id="my-component-template">
    <div>
        {{text}}, <!-- to illustrate props data passing working as usual -->
        <span ref="s1"></span>, <!-- to illustrate a normal ref -->
        <span class="nested"> <!-- to illustrate vnode.context doesn't just get the parent node -->
            <span v-my-directive></span>
        </span>
    </div>
</script>

运行此示例,我们可以看到v-my-directive在运行vm中的vm.$refs.s2函数之前,成功修改了mounted以使用指令引用DOM元素,在这里我们可以使用参考。

请注意,如果有多个元素包含指令,您可能希望某些逻辑不覆盖ref。

编码愉快!