美文网首页
vue 的 provide, inject在使用时的一个小问题

vue 的 provide, inject在使用时的一个小问题

作者: 0月 | 来源:发表于2021-10-28 00:20 被阅读0次

    背景

    项目中有个需求,需要tab形式展示不确定个数的内容,要求可配置,于是我设计了个组合组件: tab.vue, tabContent.vue 父子配合完成tab切换功能

    问题

    然后父子组件需要通信了,tab.vue 切换tab的时候需要通知tabContent.vue, 假如有两个tab A, B ;点击tab header A的时候, 显示tabContent A ,tabContent B隐藏 ;点击tab header B的时候, 显示B ,A隐藏, 怎么无感通知呢?我采用了组合组件通用的手段: provide, inject

    tab.vue :

    <div>
      <ul>
        <li 
          v-for="tabName in tabNames"
          :key="tabName"
          @click="currentTab = tabName"
        >
            {{tabName }}
        </li>
      </ul>
      <div> <slot /> </div>
    </div>
    
     props: {
       tabNames: {
          type: Array,
           required: true
        },
    },
    data() {
      return {
        currentTab: this.tabNames[0]
      }
    },
    provide: {
      tab: this //  传tab实例下去给tabContent
    }
    

    tabContent.vue :

    <div v-show="tab.currentTab === tabName">
      <slot />
    </div>
    inject: ['tab'], // 拿到tab
    props: {
      tabName: {
        type: String,
        required: true
      }
    },
    

    设计出来,看起来没啥问题

    <tab :tabNames="['A', 'B']">
      <tabContent tabName="A">A</tabContent>
      <tabContent tabName="B">B</tabContent>
    </tab>
    
    

    但是跑起来就是失效 ,A B都没有显示。在tabContent created钩子打印排查发现是this指向undefined了

    // tabContent.vue
    created() {console.log(this.tab)},
    

    方案

    知道问题, 那就好解决了,把this绑定到tab实例就好,但是

    provide: {
      tab: this //  传tab实例下去给tabContent
    }
    

    怎么绑定呢?查看文档,会有另外一种用函数的方式

    provide() {
      return {
        tab: this //  传tab实例下去给tabContent
      }
    }
    

    结果

    解决了问题

    但是为什么会这样子呢?多年的经验告诉我应该是底层函数会通过call apply的方式绑定了this到实例上
    看看源码:


    init.png
    initProvide

    有人说不推荐在业务中使用provide inject。为什么? 因为这东西在祖先组件注入会污染所有后代,同样假如有多层祖先组件,后代就不确定是哪个祖先传下来的了,不好维护。

    所以基于以上考虑,只适合在一些强耦合的组合组件中使用。 如

    • el-select, el-option
    • el-tab, el-tab-pane
    • el-table, el-table-colunm

    相关文章

      网友评论

          本文标题:vue 的 provide, inject在使用时的一个小问题

          本文链接:https://www.haomeiwen.com/subject/hgycoltx.html