我遇到了计算插槽高度和宽度的问题。我尝试在我的Perimeter组件中渲染图像,这些图像的大小为105x160。但是当我使用console.log记录clientWidth和clientHeight时,得到的结果是0x24。
我认为我的问题与此有关:在vue.js 2中,测量一次插槽被渲染后组件的高度,但我仍然无法弄清楚。我已经尝试在Perimeter组件和单个插槽组件上使用$nextTick。
在我的Perimeter组件中,我有:
我将以下内容传递给 Perimeter 组件:
更糟糕的是,当我在forEach函数中使用console.log(slot.elm)并在浏览器控制台中打开该数组时,我可以看到正确的clientHeight和clientWidth:
我认为我的问题与此有关:在vue.js 2中,测量一次插槽被渲染后组件的高度,但我仍然无法弄清楚。我已经尝试在Perimeter组件和单个插槽组件上使用$nextTick。
在我的Perimeter组件中,我有:
<template>
<div class="d-flex">
<slot></slot>
<div class="align-self-center">
<slot name="center-piece"></slot>
</div>
</div>
</template>
<script>
export default {
name: 'Perimeter',
mounted() {
this.distributeSlots();
},
updated() {
this.distributeSlots();
},
computed: {
centerRadius() {
return this.$slots['center-piece'][0].elm.clientWidth / 2;
},
},
methods: {
distributeSlots() {
let angle = 0;
const {
clientHeight: componentHeight,
clientWidth: componentWidth,
offsetTop: componentOffsetTop,
offsetLeft: componentOffsetLeft,
} = this.$el;
const componentXCenter = componentWidth / 2;
const componentYCenter = componentHeight / 2;
const slots = this.$slots.default.filter(slot => slot.tag) || [];
const step = (2 * Math.PI) / slots.length;
slots.forEach((slot) => {
slot.context.$nextTick(() => {
const { height, width } = slot.elm.getBoundingClientRect();
console.log(`height ${height}, width ${width}`);
const distanceFromCenterX = (this.centerRadius + componentXCenter) * Math.cos(angle);
const distanceFromCenterY = (this.centerRadius + componentYCenter) * Math.sin(angle);
const x = Math.round((componentXCenter + distanceFromCenterX + componentOffsetLeft) - (width / 2));
const y = Math.round((componentYCenter + distanceFromCenterY + componentOffsetTop) - (height / 2));
slot.elm.style.left = `${x}px`;
slot.elm.style.top = `${y}px`;
angle += step;
});
});
},
},
};
</script>
我也曾经编写过没有使用$nextTick的distributeSlots()方法:
distributeSlots() {
let angle = 0;
const {
clientHeight: componentHeight,
clientWidth: componentWidth,
offsetTop: componentOffsetTop,
offsetLeft: componentOffsetLeft,
} = this.$el;
const componentXCenter = componentWidth / 2;
const componentYCenter = componentHeight / 2;
const slots = this.$slots.default.filter(slot => slot.tag) || [];
const step = (2 * Math.PI) / slots.length;
slots.forEach((slot) => {
const { height, width } = slot.elm.getBoundingClientRect();
const distanceFromCenterX = (this.centerRadius + componentXCenter) * Math.cos(angle);
const distanceFromCenterY = (this.centerRadius + componentYCenter) * Math.sin(angle);
const x = Math.round((componentXCenter + distanceFromCenterX + componentOffsetLeft) - (width / 2));
const y = Math.round((componentYCenter + distanceFromCenterY + componentOffsetTop) - (height / 2));
slot.elm.style.left = `${x}px`;
slot.elm.style.top = `${y}px`;
angle += step;
});
},
我将以下内容传递给 Perimeter 组件:
我将以下内容传递给 Perimeter 组件:
<template>
<perimeter>
<div v-for="(book, index) in books.slice(0, 6)" v-if="book.image" :key="book.asin" style="position: absolute">
<router-link :to="{ name: 'books', params: { isbn: book.isbn }}">
<img :src="book.image" />
</router-link>
</div>
<perimeter>
</template>
更糟糕的是,当我在forEach函数中使用console.log(slot.elm)并在浏览器控制台中打开该数组时,我可以看到正确的clientHeight和clientWidth: