$ nextTick循环返回对象

时间:2019-06-10 21:36:50

标签: javascript vue.js

我有一种获取div样式的方法

<div v-for="(frame, frameIndex) in frames" :key="frameIndex">
  <div :styles="getStylesForNode(node, frameIndex)"></div>
</div>


methods: {
  getStylesForNode(node, frameIndex) {
    this.$nextTick(() => {
      const frame = this.$refs[`frame${frameIndex}`][0]
      const framePosition = frame.getBoundingClientRect()
      return {
        width: node.width - framePosition.width
      }
    })
  }
}

它返回空对象,是否有某种方法可以使它工作? 我找到了这个way,但不适合我的问题。

1 个答案:

答案 0 :(得分:0)

很有可能,您的问题是this.$refs['frame${index}'][0]在安装组件之前引发了错误(因为在安装之前无法使用$refs)。

防止错误,直到$refs存在:

methods: {
  getStylesForNode(node, frameIndex) {

    // guard against $refs not yet being defined
    if (this.$refs[`frame${index}`]) {
      const frame = this.$refs[`frame${index}`][0];
      if (frame && typeof frame.getBoundingClientRect === 'function') {
        return {
          width: `${node.width - frame.getBoundingClientRect().width}px`
        }
      }
    }

    // return a safe, empty style, if you haven't returned on happy path
    return {};
  }
},

然后使用mounted()重新计算this.$forceUpdate()中的方法。

mounted() {
  this.$forceUpdate();
}

看到它正常工作:

Vue.config.productionTip = false;
Vue.config.devtools = false;

new Vue({
  el: '#hook',
  template: '#template',
  data: () => ({ data: [...Array(5).keys()] }),
  methods: {
    getStyle(el) {
      const span = this.$refs[`el-${el}`];
      return span ? {
          top: `${span[0].getBoundingClientRect().left}px`,
          borderTop: '1px solid red'
        } : {};
    }
  },
  beforeMount() {
    console.log('in beforeMount() $refs count is', Object.keys(this.$refs).length);
  },
  mounted() {
    console.log('in mounted() $refs count is', Object.keys(this.$refs).length);
    // we can now trigger an update to recalculate method...
    this.$forceUpdate();
  }
})
#app span {
  position: relative;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script type="text/template" id="template">
  <div id="app">
    <span
      v-for="el in data"
      v-text="el"
      :key="el"
      :ref="`el-${el}`"
      :style="getStyle(el)"></span>
  </div>
</script>
<div id="hook"></div>