【问题标题】:this.$children is behaving as if it were reactivethis.$children 表现得好像是被动的
【发布时间】:2020-11-16 03:12:35
【问题描述】:

官方docthis.$children 没有反应,

当前实例的直接子组件。请注意,$children 没有订单保证,而且它不是响应式的......

因此,任何更改都不应触发任何重新渲染。 [this.$children api 已从 vuejs v3 中删除,因此它仅适用于 v2.x。]

我觉得这很有趣...https://codepen.io/tatimblin/pen/oWKdjR

上面沙盒中的代码是使用slot & this.$childen api 实现的tab UI 的演示。 最初tabs 组件持有对this.$children 数组的引用,这里有一个日志:

有趣的是,tabisActive 属性正在使用该数组进行更改,但它反映在每个组件中,导致重新渲染.. 我不确定这里发生了什么......也许我错过了一些东西。

模板:

<div id="root" class="container">

  <tabs>
    <tab name="Services" :selected="true">
      <h1>What we do</h1>
    </tab>
    <tab name="Pricing">
      <h1>How much we do it for</h1>
    </tab>
    <tab name="About Us">
      <h1>Why we do it</h1>
    </tab>
  </tabs>

</div>

JS:

Vue.component('tabs', {
    template: `
        <div>
            <div class="tabs">
              <ul>
                <li v-for="tab in tabs" :class="{ 'is-active': tab.isActive }">
                    <a :href="tab.href" @click="selectTab(tab)">{{ tab.name }}</a>
                </li>
              </ul>
            </div>

            <div class="tabs-details">
                <slot></slot>
            </div>
        </div>
    `,
    
    data() {
        return {tabs: [] };
    },
    
    created() {
        
        this.tabs = this.$children;
        
    },
    methods: {
        selectTab(selectedTab) {
            this.tabs.forEach(tab => {
                tab.isActive = (tab.name == selectedTab.name); 
               // this is how the isActive prop is changed, using this.$children
            });
        }
    }
});

Vue.component('tab', {
    
    template: `

        <div v-show="isActive"><slot></slot></div>

    `,
    
    props: {
        name: { required: true },
        selected: { default: false}
    },
    
    data() {
        
        return {
            isActive: false
        };
        
    },
    
    computed: {
        
        href() {
            return '#' + this.name.toLowerCase().replace(/ /g, '-');
        }
    },
    
    mounted() {
        
        this.isActive = this.selected;
        
    }
});

new Vue({
    el: '#root'
});

【问题讨论】:

  • "tab 的名称属性正在使用该数组进行更改"。在哪里?唯一的设置选项卡name 道具是模板
  • @Dan my bad.. 我的意思是isActive porp..,我已经在评论中正确提到了道具正在改变的地方。

标签: vue.js vuejs2 vue-reactivity


【解决方案1】:

子级是响应式的,因为它们本身就是 Vue 组件,除了 tabs 父级之外,它们已经具有响应式的全部功能。

doc 引用是指在其他情况下不会自行反应的内容。这种区别可能会更清楚一些。另一方面,如果插槽内容不是具有isActive 属性的组件,则tabs 将无法正常工作,这会形成紧密耦合。它不适用于原始 HTML 插槽内容,例如:

  <tabs>
    <div>
      Hi, I'm not a component
    </div>
  </tabs>

【讨论】:

  • 谢谢.. 实际上this.$children 中引用的 vue 组件确实是反应性的.. 不是this.$children 本身,我现在明白了..
  • 如何在 vuejs v3 中获得 slot 内部渲染的 vue 组件?
  • 你可以使用this.$slots.default()
  • 我试过了..default() 方法返回的值不是vue components,它们是别的东西.. 确实没有反应性..
  • 它们是 VNode,它们是响应式的,但您无法从父级向下获取它们的数据。但是,无论如何,这对this.$children 来说有点小题大做,这可能就是他们删除该功能的原因(违反one-way data flow)。
猜你喜欢
  • 2022-07-12
  • 2016-04-07
  • 2018-02-22
  • 1970-01-01
  • 2013-02-09
  • 1970-01-01
  • 1970-01-01
  • 2014-09-09
  • 2011-04-13
相关资源
最近更新 更多