Дочерний компонент vuetify `v-tabs` возвращает offsetWidth как 0 - PullRequest
0 голосов
/ 25 сентября 2018

Вот кодовая ручка, которая воспроизводит сценарий: https://codepen.io/anon/pen/vzqgJB

У меня есть router-view внутри vuetify's v-app.

<div id="app">
  <v-app>
    <v-content>
      <v-container>
        {{$route.path}}
        <router-view/>
      </v-container>
    </v-content>
  </v-app>
</div>

Конфигурация маршрутизации следующая:

const routes = [
    { path: '', component: tabsComponent, 
      children:[
        { path: '', component: component1 },
        { path: 'component2', component: component2 }
      ]
    },
]

Я использую v-tabs компонент Vuetify для рендеринга 2 вкладок, которые загружают component1 и component2 соответственно.

var tabsComponent = Vue.component('tabsComponent',{
  components:{
    component2,
    component1
  },
  name:'tabsComponent',
  template: `
     <v-tabs>
        <v-tab to="/">Tab 1</v-tab>
       <v-tab to="/component2">Tab 2</v-tab>
       <v-tabs-items>
          <v-tab-item id="/">
            <component1></component1>
          </v-tab-item>
          <v-tab-item id="/component2">
            <component2></component2>
          </v-tab-item>
        </v-tabs-items>
     </v-tabs>
`,
   mounted(){
    this.$nextTick(()=>{
      console.log("tabs")
      console.log(this.$el.offsetWidth)
    })
  }
})

Проблема, с которой я сталкиваюсь, заключается в том, чтокогда component1 смонтирован, this.$el.offsetWidth возвращается как 0.

  var component1 = Vue.component('component1',{
    name: 'component1',
      template: `
         <v-container fluid>John </v-container>
      `,
      mounted(){
        this.$nextTick(()=>{
          console.log("component1")
          console.log(this.$el.offsetWidth) // This is printed as 0
        })
      }
    })

Я не могу понять, почему ширина возвращается как 0, даже если родительские компоненты имеют ненулевое значение offsetWidth,Любая помощь будет оценена.

1 Ответ

0 голосов
/ 25 сентября 2018

mounted перехват крюка в дочернем компоненте перед монтированием перехвата в родительском : монтирование перехватчика в дочернем элементе, монтирование перехватчика в родительском компоненте и, наконец, рендеринг в dom.Таким образом, в дочернем компоненте вы находитесь в двух шагах от рендера Вы можете делать то, что хотите, с двумя сложенными $nextTick или setTimeout (обратный вызов setTimeout получает управление после того, как vue выполняет все его действия):

mounted(){
  this.$nextTick(()=>{
    this.$nextTick(()=>{
      console.log("component1")
      console.log(this.$el.offsetWidth)
    })
  })
}

или

mounted(){
  setTimeout(()=> {
    console.log("component1")
    console.log(this.$el.offsetWidth)
  })
}

Иллюстрацияс крючки Vue Parent и Child жизненного цикла :

enter image description here


обновите ваш комментарий:

Да, вы не можете получить offsetWidth неактивной вкладки с display: none.Но смещение всех вкладок равно друг другу?В любом случае, вы можете динамически отслеживать активную вкладку.Используйте v-model на вашем tabsComponent и добавьте метод наблюдения, в котором вы можете получить свои метрики, когда вкладка видна.Также вы должны добавить ref как к своим компонентам, так и к внутренним контейнерам (установив ref-имя компонента, равное пути табуляции, вы можете использовать activeTab для доступа к внутренним ссылкам активного компонента).

В шаблонах:

<v-container fluid ref="div">John</v-container>
# ...
<div id="component2" ref="div">Jinny</div>
# ...
<v-tabs v-model='activeTab'>
# ...
<component1 ref="/"></component1>
<component2 ref="/jinny"></component2>

В скрипте:

data: function () {
  return {
    activeTab: null
  }
},
watch: {
  activeTab: function () {
    this.$nextTick(()=> {
      console.log(this.$refs[this.activeTab].$refs.div.offsetWidth) 
    })
  }
}

обновлен код ручки с методом часов: https://codepen.io/anon/pen/qMeYGZ

...