Vue 开发实战基础篇 # 13:如何优雅地获取跨层级组件实例(拒绝递归)

Posted 凯小默

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue 开发实战基础篇 # 13:如何优雅地获取跨层级组件实例(拒绝递归)相关的知识,希望对你有一定的参考价值。

说明

【Vue 开发实战】学习笔记。

ref 引用信息

递归查找

  • 代码繁琐.
  • 性能低效

callback ref

  • 主动通知(setXxxRef)
  • 主动获取(getXxxRef)

比如E节点更新就通知A组件,A组件进行ref的缓存即可

组件A

<template>
  <div class="border">
    <h1>A 结点</h1>
    <button @click="getHRef">获取子孙节点 E Ref</button>
    <ChildrenB />
    <ChildrenC />
    <ChildrenD />
  </div>
</template>
<script>
import ChildrenB from "./ChildrenB";
import ChildrenC from "./ChildrenC";
import ChildrenD from "./ChildrenD";
export default 
  components: 
    ChildrenB,
    ChildrenC,
    ChildrenD
  ,
  provide() 
    return 
      setChildrenRef: (name, ref) => 
        console.log("A 组件 setChildrenRef", name);
        this[name] = ref;
      ,
      getChildrenRef: name => 
        console.log("A 组件 getChildrenRef", name);
        return this[name];
      ,
      getRef: () => 
        console.log("A 组件 getRef");
        return this;
      
    ;
  ,
  data() 
    return 
      color: "blue"
    ;
  ,
  methods: 
    getHRef() 
      console.log(this.childrenE);
    
  
;
</script>

组件D

<template>
  <div class="border1">
    <h2>D 结点</h2>
    <ChildrenG />
    <ChildrenH v-ant-ref="c => setChildrenRef('childrenH', c)" />
    <ChildrenI />
  </div>
</template>
<script>
import ChildrenG from "./ChildrenG";
import ChildrenH from "./ChildrenH";
import ChildrenI from "./ChildrenI";
export default 
  components: 
    ChildrenG,
    ChildrenH,
    ChildrenI
  ,
  inject: 
    setChildrenRef: 
      default: () => 
    
  
;
</script>

组件E

<template>
  <div class="border2">
    <h3 v-ant-ref="c => setChildrenRef('childrenE', c)">
      E 结点
    </h3>
  </div>
</template>
<script>
export default 
  components: ,
  inject: 
    setChildrenRef: 
      default: () => 
    
  
;
</script>

组件F

<template>
  <div class="border2">
    <h3>F 结点</h3>
    <button @click="getARef">获取祖先节点 A Ref</button>
    <button @click="getHRef">获取同级节点 H Ref</button>
  </div>
</template>
<script>
export default 
  components: ,
  inject: 
    getParentRef: 
      from: "getRef",
      default: () => 
    ,
    getParentChildrenRef: 
      from: "getChildrenRef",
      default: () => 
    
  ,
  methods: 
    getARef() 
      console.log(this.getParentRef());
    ,
    getHRef() 
      console.log(this.getParentChildrenRef("childrenH"));
    
  
;
</script>

然后点击三个按钮

这里面使用了 v-ant-ref 这个指令,用于通知上层节点更新。我们可以找一下依赖 vue-ref 这个包,看一下指令源码

"use strict";

Object.defineProperty(exports, "__esModule", 
  value: true
);
exports.default = 
  install: function install(Vue) 
    var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ;
    var directiveName = options.name || 'ref';
    Vue.directive(directiveName, 
      bind: function bind(el, binding, vnode) 
        binding.value(vnode.componentInstance || el, vnode.key);
      ,
      update: function update(el, binding, vnode, oldVnode) 
        if (oldVnode.data && oldVnode.data.directives) 
          var oldBinding = oldVnode.data.directives.find(function (directive) 
            var name = directive.name;
            return name === directiveName;
          );
          if (oldBinding && oldBinding.value !== binding.value) 
            oldBinding && oldBinding.value(null, oldVnode.key);
            binding.value(vnode.componentInstance || el, vnode.key);
            return;
          
        
        // Should not have this situation
        if (vnode.componentInstance !== oldVnode.componentInstance || vnode.elm !== oldVnode.elm) 
          binding.value(vnode.componentInstance || el, vnode.key);
        
      ,
      unbind: function unbind(el, binding, vnode) 
        binding.value(null, vnode.key);
      
    );
  
;

完整demo源码可以参考这个https://github.com/kaimo313/vue-development-practice/tree/master/vue-demo/src/views/demo13

以上是关于Vue 开发实战基础篇 # 13:如何优雅地获取跨层级组件实例(拒绝递归)的主要内容,如果未能解决你的问题,请参考以下文章

Vue 开发实战实战篇 # 35:如何高效地使用Mock数据进行开发

Vue 开发实战实战篇 # 44:如何高效地构建打包发布

Vue 开发实战基础篇 # 8:如何触发组件的更新

16.如何优雅地获取跨层级组件实例(拒绝递归)

Vue 开发实战学习笔记48篇(完结)

Vue 开发实战基础篇 # 2:组件基础及组件注册