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


    说明

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

    ref 引用信息

    在这里插入图片描述

    递归查找

    • 代码繁琐.
    • 性能低效

    在这里插入图片描述

    callback ref

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

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

    组件A

    <template>
      <div class="border">
        <h1>A 结点h1>
        <button @click="getHRef">获取子孙节点 E Refbutton>
        <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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    组件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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    组件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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    组件F

    <template>
      <div class="border2">
        <h3>F 结点h3>
        <button @click="getARef">获取祖先节点 A Refbutton>
        <button @click="getHRef">获取同级节点 H Refbutton>
      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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述

    然后点击三个按钮

    在这里插入图片描述

    这里面使用了 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);
          }
        });
      }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

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

  • 相关阅读:
    基于SSM的电子设备销售网站的设计与实现
    m基于matlab的BTS天线设计,带GUI界面
    【RuoYi-Vue-Plus】扩展笔记 06 - 数据源 Druid 修改为 HikariCP
    【七:(测试用例)spring boot+testng+xml+mock实现用例管理+数据校验】
    网络之眼:XSS与CSRF攻击的深度防范
    Apache Kudu的Transaction Semantics事务语义
    C语言速成笔记 —— 考点详解 & 知识点图解
    电机与拖动(1)直流电机
    神奇代码恢复工具
    大数据个性化推荐,AWS终端用户解决方案
  • 原文地址:https://blog.csdn.net/kaimo313/article/details/126700647