首页 > 专栏 > 前端 > 文章详情
如何优雅的获取跨层级组件实例(不用递归) 发布于:2021-04-27 08:52:37   来源:Vue   查看:37  讨论:0
但是随着业务的增长,难免会访问到我们Vue组件的实例的一个情况。7jb易塔云建站-模板下载,web开发资源,技术博客
1,比如我们使用echarts,业界很知名的一个统计可视化库,我们就很难免会涉及到获取组件实例的一个情况。7jb易塔云建站-模板下载,web开发资源,技术博客
2,再比如,我们需要一个input节点,让它手动的去处于一个focus的状态,这时候我们依然需要去访问这个实例。7jb易塔云建站-模板下载,web开发资源,技术博客
7jb易塔云建站-模板下载,web开发资源,技术博客
一、正常情况下使用this.$refs.xxx获取需要的DOM节点或组件实例。7jb易塔云建站-模板下载,web开发资源,技术博客
7jb易塔云建站-模板下载,web开发资源,技术博客
基于这些情况,Vue预留了一个API,就是ref。通过this.ref.xxx,xxx就是我们给这个组件起的挂载在组件上的这个名字。
<!-- `vm.$refs.p` will be the DOM node -->7jb易塔云建站-模板下载,web开发资源,技术博客
<p ref="p">hello</p>7jb易塔云建站-模板下载,web开发资源,技术博客
7jb易塔云建站-模板下载,web开发资源,技术博客
<!-- `vm.$refs.child` will be the child component instance -->7jb易塔云建站-模板下载,web开发资源,技术博客
<child-component ref="child"></child-component>
都可以通过this.refs.xxx来访问到这个实例,但是这里需要注意的一点是:7jb易塔云建站-模板下载,web开发资源,技术博客
7jb易塔云建站-模板下载,web开发资源,技术博客
7jb易塔云建站-模板下载,web开发资源,技术博客
如果是原生DOM,比如p节点,我们获取到的就是真实DOM元素p,如果是自定义组件,我们获取到的就是这个组件的实例。7jb易塔云建站-模板下载,web开发资源,技术博客
7jb易塔云建站-模板下载,web开发资源,技术博客
p元素的使用代码:
<template>7jb易塔云建站-模板下载,web开发资源,技术博客
    <div>7jb易塔云建站-模板下载,web开发资源,技术博客
        <p ref="p">hello world</p>7jb易塔云建站-模板下载,web开发资源,技术博客
        <button @click="showPDOM">p的按钮</button>7jb易塔云建站-模板下载,web开发资源,技术博客
    </div>7jb易塔云建站-模板下载,web开发资源,技术博客
</template>7jb易塔云建站-模板下载,web开发资源,技术博客
<script>7jb易塔云建站-模板下载,web开发资源,技术博客
import ChildComponent from './ChildComponent.vue'7jb易塔云建站-模板下载,web开发资源,技术博客
export default {7jb易塔云建站-模板下载,web开发资源,技术博客
    methods: {7jb易塔云建站-模板下载,web开发资源,技术博客
        showPDOM: function() {7jb易塔云建站-模板下载,web开发资源,技术博客
            console.log(this.$refs.p);7jb易塔云建站-模板下载,web开发资源,技术博客
        },7jb易塔云建站-模板下载,web开发资源,技术博客
    }7jb易塔云建站-模板下载,web开发资源,技术博客
}7jb易塔云建站-模板下载,web开发资源,技术博客
</script>
自定义组件的使用:7jb易塔云建站-模板下载,web开发资源,技术博客
父组件:
7jb易塔云建站-模板下载,web开发资源,技术博客
 
<template>7jb易塔云建站-模板下载,web开发资源,技术博客
    <div>7jb易塔云建站-模板下载,web开发资源,技术博客
        <p ref="p">hello world</p>7jb易塔云建站-模板下载,web开发资源,技术博客
        <button @click="showPDOM">p的按钮</button>7jb易塔云建站-模板下载,web开发资源,技术博客
        <child-component ref="child" v-on:showChild="consoleLog"></child-component>7jb易塔云建站-模板下载,web开发资源,技术博客
    </div>7jb易塔云建站-模板下载,web开发资源,技术博客
</template>7jb易塔云建站-模板下载,web开发资源,技术博客
<script>7jb易塔云建站-模板下载,web开发资源,技术博客
import ChildComponent from './ChildComponent.vue'7jb易塔云建站-模板下载,web开发资源,技术博客
export default {7jb易塔云建站-模板下载,web开发资源,技术博客
    components: {7jb易塔云建站-模板下载,web开发资源,技术博客
        ChildComponent7jb易塔云建站-模板下载,web开发资源,技术博客
    },7jb易塔云建站-模板下载,web开发资源,技术博客
    methods: {7jb易塔云建站-模板下载,web开发资源,技术博客
        showPDOM: function() {7jb易塔云建站-模板下载,web开发资源,技术博客
            console.log(this.$refs.p);7jb易塔云建站-模板下载,web开发资源,技术博客
        },7jb易塔云建站-模板下载,web开发资源,技术博客
        consoleLog: function() {7jb易塔云建站-模板下载,web开发资源,技术博客
            console.log(this.$refs.child)7jb易塔云建站-模板下载,web开发资源,技术博客
        }7jb易塔云建站-模板下载,web开发资源,技术博客
    }7jb易塔云建站-模板下载,web开发资源,技术博客
}7jb易塔云建站-模板下载,web开发资源,技术博客
</script>
子组件:
<template>7jb易塔云建站-模板下载,web开发资源,技术博客
    <div>7jb易塔云建站-模板下载,web开发资源,技术博客
        <button @click="$emit('showChild')">按钮</button>7jb易塔云建站-模板下载,web开发资源,技术博客
    </div>7jb易塔云建站-模板下载,web开发资源,技术博客
</template>
this.refs.xxx可以方便的获取到当前节点的上下文环境,如果说要获取跨层级组件的一个实例,那就很不方便了,如果获取父组件,通过parent.refs.xxx;如果获取子组件的,通过children.refs.xxx。如果层级多的时候,就不方便了。7jb易塔云建站-模板下载,web开发资源,技术博客
7jb易塔云建站-模板下载,web开发资源,技术博客
7jb易塔云建站-模板下载,web开发资源,技术博客
通过递归的方式,一层一层的去找。比较繁琐。7jb易塔云建站-模板下载,web开发资源,技术博客
7jb易塔云建站-模板下载,web开发资源,技术博客
二、使用ant-ref插件,唐金州老师开源项目。7jb易塔云建站-模板下载,web开发资源,技术博客
7jb易塔云建站-模板下载,web开发资源,技术博客
熟悉react的朋友都知道,React中也提供了Ref(Reference引用)的API。实现方式是通过callback回调。7jb易塔云建站-模板下载,web开发资源,技术博客
7jb易塔云建站-模板下载,web开发资源,技术博客
我现在要从A节点获取E节点的实例。7jb易塔云建站-模板下载,web开发资源,技术博客
7jb易塔云建站-模板下载,web开发资源,技术博客
A节点设置一个钩子函数,E实例生成或者更新之后,主动去调用这个钩子函数,来通知A节点,我这个实例已经生成好了,或者我这个实例有更新,需要告诉这个A节点。7jb易塔云建站-模板下载,web开发资源,技术博客
然后A节点将这个实例进行缓存就可以了。每次A节点需要访问的时候,总是能拿到最新的数据,因为E节点更新之后已经主动地告诉了A节点。7jb易塔云建站-模板下载,web开发资源,技术博客
7jb易塔云建站-模板下载,web开发资源,技术博客
A节点源码:
provide() {7jb易塔云建站-模板下载,web开发资源,技术博客
    return {7jb易塔云建站-模板下载,web开发资源,技术博客
        setChildrenRef: (name, ref) => {7jb易塔云建站-模板下载,web开发资源,技术博客
            this[name] = ref;   //把传递过来的ref进行缓存7jb易塔云建站-模板下载,web开发资源,技术博客
        },7jb易塔云建站-模板下载,web开发资源,技术博客
        getChildrenRef: name => {7jb易塔云建站-模板下载,web开发资源,技术博客
            return this[name];  //或区域需要的name的ref7jb易塔云建站-模板下载,web开发资源,技术博客
        },7jb易塔云建站-模板下载,web开发资源,技术博客
        getRef: () => {7jb易塔云建站-模板下载,web开发资源,技术博客
            return this;7jb易塔云建站-模板下载,web开发资源,技术博客
        }7jb易塔云建站-模板下载,web开发资源,技术博客
    }7jb易塔云建站-模板下载,web开发资源,技术博客
},
7jb易塔云建站-模板下载,web开发资源,技术博客
子节点E的源码结构:7jb易塔云建站-模板下载,web开发资源,技术博客
 
<template>7jb易塔云建站-模板下载,web开发资源,技术博客
  <div class="border2">7jb易塔云建站-模板下载,web开发资源,技术博客
    <h3 v-ant-ref="c => setChildrenRef('childrenE', c)">7jb易塔云建站-模板下载,web开发资源,技术博客
      E 结点7jb易塔云建站-模板下载,web开发资源,技术博客
    </h3>7jb易塔云建站-模板下载,web开发资源,技术博客
  </div>7jb易塔云建站-模板下载,web开发资源,技术博客
</template>7jb易塔云建站-模板下载,web开发资源,技术博客
<script>7jb易塔云建站-模板下载,web开发资源,技术博客
export default {7jb易塔云建站-模板下载,web开发资源,技术博客
  components: {},7jb易塔云建站-模板下载,web开发资源,技术博客
  inject: {7jb易塔云建站-模板下载,web开发资源,技术博客
    setChildrenRef: {7jb易塔云建站-模板下载,web开发资源,技术博客
      default: () => {}7jb易塔云建站-模板下载,web开发资源,技术博客
    }7jb易塔云建站-模板下载,web开发资源,技术博客
  }7jb易塔云建站-模板下载,web开发资源,技术博客
};7jb易塔云建站-模板下载,web开发资源,技术博客
</script>

评论

  • 匿名