收藏
回答

组件内怎么用 wx.createSelectorQuery().in(this) 获得slot?

子组件:/components/timeline/timeline-item

<view class="timeline-item">
  <view class="timeline-item-dot"></view>
  
  <text class="label">{{ label }}</text>
  
  <view class="value">
    <text>{{ value }}</text>
    <text wx:if="{{ unit }}" class="unit">{{ unit }}</text>
  </view>
</view>


Component({
  // ---- 建立与父组件的关系 ----
  relations: {
    '../timeline': {
      type: 'parent' // 关联的父组件
    }
  },
​
  // ---- 定义组件可接收的外部属性 ----
  properties: {
    label: String,
    value: String,
    unit: String
  }
});


​
@text-color-label: #888888;
@text-color-value: #333333;
@font-size-base: 16px;
​
.timeline-item {
  display: flex;
  align-items: center;
  margin-bottom: 28px;
  font-family: sans-serif;
​
  &:last-child {
    margin-bottom: 0;
  }
}
​
.timeline-item-dot {
  width: 8px;
  height: 8px;
  box-sizing: border-box;
  border: 2px solid @primary-color;
  background: rgb(255, 255, 255);
​
  flex-shrink: 0;
  border-radius: 50%;
  margin-right: 7px;
  z-index: 1;
}
​
.label {
  color: rgb(131, 131, 131);
  font-family: 思源黑体 CN;
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  letter-spacing: 0px;
  text-align: left;
​
  margin-right: auto;
}
​
.value {
  display: flex;
  align-items: baseline;
​
  color: rgb(29, 34, 30);
  font-family: 思源黑体 CN;
  font-size: 14px;
  font-weight: 400;
  line-height: 21px;
  letter-spacing: 0px;
  text-align: right;
​
  .unit {
    font-size: 0.9em;
    color: @text-color-value;
    margin-left: 4px;
    font-weight: 400;
  }
}
​

父组件:/components/timeline/timeline

<view class="timeline">
  <!-- 链接点的装饰线 -->
  <view class="timeline-line" style="{{ lineStyle }}"></view>
  
  <slot></slot>
</view>


Component({
  relations: {
    './timeline-item/timeline-item': {
      type: 'child', // 关联的子组件
      linked() {
        // 每当有 timeline-item 插入时,重新计算线条
        if (this.data.timer) clearTimeout(this.data.timer);
        this.data.timer = setTimeout(() => {
          this.updateLinePosition();
        }, 30);
      },
      unlinked() {
        // 每当有 timeline-item 移除时,重新计算线条
        if (this.data.timer) clearTimeout(this.data.timer);
        this.data.timer = setTimeout(() => {
          this.updateLinePosition();
        }, 30);
      }
    }
  },
​
  data: {
    lineStyle: '',
    timer: 0
  },
​
  methods: {
    updateLinePosition() {
      // 使用 wx.nextTick 确保在 DOM 更新后再执行查询
      wx.nextTick(() => {
        const query = wx.createSelectorQuery().in(this);
​
        // 查询所有子组件的圆点 FIXME: 找不到子组件
        query.selectAll('.timeline-item-dot').boundingClientRect();
​
        // 查询父容器 .timeline 的位置信息,而不是线条自身
        query.select('.timeline').boundingClientRect();
​
        query.exec((res) => {
          const [dots, wrapper] = res;
​
          console.debug(dots, wrapper);
​
          // 至少需要两个节点才能形成一条线
          if (dots && dots.length > 1 && wrapper) {
            const firstDot = dots[0];
            const lastDot = dots[dots.length - 1];
​
            const lineTop = firstDot.top + firstDot.height / 2 - wrapper.top;
            const lineHeight = lastDot.top + lastDot.height / 2 - (firstDot.top + firstDot.height / 2);
​
            this.setData({
              lineStyle: `top: ${lineTop}px; height: ${lineHeight}px;`
            });
          } else {
            // 如果子项少于2个,则不显示线条
            this.setData({ lineStyle: 'height: 0;' });
          }
        });
      });
    }
  }
});



.timeline {
  position: relative;
  background-color: #ffffff;
}
​
.timeline-line {
  position: absolute;
  left: 20.5px; // 与 timeline-item 的圆点中心对齐
  width: 1px;
  box-sizing: border-box;
  border: 1px solid rgb(235, 235, 235);
  z-index: 0;
  // top 和 height 由 TS 动态设定
}


回答关注问题邀请回答
收藏

1 个回答

  • 智能回答 智能回答 本次回答由AI生成
    2025-06-17
    有用
登录 后发表内容