vue3 TS 动态改变class的宽度?

GbSplitPanel组件

import { defineComponent, ref, unref, computed, PropType, watch } from "vue";
import resizer from "./resizer";
import "./style/index.scss";

export interface ContextProps {
  minPercent: number;
  defaultPercent: number;
  split: string;
}

export default defineComponent({
  name: "splitPane",
  components: { resizer },
  props: {
    splitSet: {
      type: Object as PropType<ContextProps>,
      require: true
    }
  },
  emits: ["resize"],
  setup(props, ctx) {
    const active = ref(false);
    const hasMoved = ref(false);
    const percent = ref(props.splitSet?.defaultPercent);
    const type = props.splitSet?.split === "vertical" ? "width" : "height";
    const resizeType = props.splitSet?.split === "vertical" ? "left" : "top";
    const leftClass = ref([
      "splitter-pane splitter-paneL",
      props.splitSet?.split
    ]);
    const rightClass = ref([
      "splitter-pane splitter-paneR",
      props.splitSet?.split
    ]);
    const userSelect = computed(() => {
      return active.value ? "none" : "";
    });

    const cursor = computed(() => {
      return active.value
        ? props.splitSet?.split === "vertical"
          ? "col-resize"
          : "row-resize"
        : "";
    });

    const onClick = (): void => {
      if (!hasMoved.value) {
        percent.value = 50;
        ctx.emit("resize", percent.value);
      }
    };

    const onMouseDown = (): void => {
      active.value = true;
      hasMoved.value = false;
    };

    const onMouseUp = (): void => {
      active.value = false;
    };

    const onMouseMove = (e: any): void => {
      if (e.buttons === 0 || e.which === 0) {
        active.value = false;
      }

      if (active.value) {
        let offset = 0;
        let target = e.currentTarget;
        if (props.splitSet?.split === "vertical") {
          while (target) {
            offset += target.offsetLeft;
            target = target.offsetParent;
          }
        } else {
          while (target) {
            offset += target.offsetTop;
            target = target.offsetParent;
          }
        }

        const currentPage =
          props.splitSet?.split === "vertical" ? e.pageX : e.pageY;
        const targetOffset =
          props.splitSet?.split === "vertical"
            ? e.currentTarget.offsetWidth
            : e.currentTarget.offsetHeight;
        const percents =
          Math.floor(((currentPage - offset) / targetOffset) * 10000) / 100;

        if (
          percents > props.splitSet?.minPercent &&
          percents < 100 - props.splitSet?.minPercent
        ) {
          percent.value = percents;
        }

        ctx.emit("resize", percent.value);

        hasMoved.value = true;
      }
    };
    watch(props.splitSet, newVal => {
      console.log("监听啊", newVal);
    });
    return () => (
      <>
        <div
          class="vue-splitter-container clearfix"
          style={(unref(cursor), unref(userSelect))}
          onMouseup={() => onMouseUp()}
          onMousemove={() => onMouseMove(event)}
        >
          <div
            class={unref(leftClass)}
            style={{ [unref(type)]: unref(percent) + "%" }}
          >
            {ctx.slots.paneL()}
          </div>
          <resizer
            style={`${unref([resizeType])}:${unref(percent)}%`}
            split={props.splitSet?.split}
            onMousedown={() => onMouseDown()}
            onClick={() => onClick()}
          ></resizer>
          <div
            class={unref(rightClass)}
            style={{ [unref(type)]: 100 - unref(percent) + "%" }}
          >
            {ctx.slots.paneR()}
          </div>
          <div v-show={unref(active)} class="vue-splitter-container-mask"></div>
        </div>
      </>
    );
  }
});

引入GbSplitPanel组件

<splitpane :splitSet="settingLR">
    <template #paneL>text</template>
    <template #paneR>text1</template>
</splitpane>

const settingLR: ContextProps = reactive({
  minPercent: 50,
  defaultPercent: 50,
  split: "vertical"
});

需要点击红色圈让这个列表的宽度改为100%; 默认为50%,点击可以展开,宽度到100。
我在点击事件上设置
minPercent: 100,defaultPercent: 100
打印出来如:

const settingLR: ContextProps = reactive({
  minPercent: 100,
  defaultPercent: 100,
  split: "vertical"
});

但是视图宽度没有什么改变。宽度还是没有改变,望各位大佬帮忙看看?
GbSplitPanel组件里面的 props.splitSet 监听没有打印出来。

阅读 3.4k
2 个回答

已解决这个问题

你在使用组件的时候没有传入 emit 方法吧,所以 settingLR 好像没有改变?这样不触发 watch 也是正常的。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题