vuetify`v-tabs`的子组件将offsetWidth返回为0

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vuetify`v-tabs`的子组件将offsetWidth返回为0相关的知识,希望对你有一定的参考价值。

以下是重现场景的codepen:https://codepen.io/anon/pen/vzqgJB

我在quetify的router-view里面有一个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 }
      ]
    },
]

我使用Vuetify的v-tabs组件来渲染分别加载component1component2的2个标签。

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
        })
      }
    })

虽然父组件的offsetWidth非零,但我无法弄清楚为什么宽度返回为0。任何帮助,将不胜感激。

答案

在父组件中挂载钩子之前触发的子组件中的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 and Child lifecycle hooks的插图:

enter image description here


更新您的评论:

是的,你不能用offsetWidth获得非活动标签的display: none。但所有标签的偏移是相等的吗?无论如何,您可以动态跟踪活动选项卡。在v-model上使用tabsComponent并添加监视方法,您可以在选项卡可见时获取指标。此外,您应该将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) 
    })
  }
}

使用watch方法更新了codepen:https://codepen.io/anon/pen/qMeYGZ

以上是关于vuetify`v-tabs`的子组件将offsetWidth返回为0的主要内容,如果未能解决你的问题,请参考以下文章

Vuetify v-spacer 不适用于 v-tabs

Vuetify:如何预选活动标签?

使用路由或查询更改 vuetify 选项卡

重构vue单文件组件

在Vuetify和Vue JS中将道具传递给父母

v-card 中的 bootstrap-vue v-tabs 呈现“未定义”