vue实现滑动切换:切换选项时滑块有滑动过渡的效果

效果图

思路:

1. 高亮的色块是独立的一个盒子,需要插入当前激活的内容用来撑开色块盒子的宽度,这样色块的宽度就会和当前激活的内容宽度一致,色块的字体颜色设置透明即可

2. 色块滑动的距离是读当前激活元素的offsetLeft,赋值给色块盒子的translateX 属性

3. 使用vue3的新属性,在css中使用v-bind()动态的设置可变化的属性

4. 在色块盒子加上过渡的属性transition,即可实现色块的滑动过度效果

实现代码

// 新建CSlideSwitch.vue组件
<template>
	<div class="c-slide-switch">
		<div class="container">
      <!-- silder 是高亮的颜色 -->
			<span class="slider" :class="{ 'is-transition': animation }">{{ showSliderName }}</span>
			<span
				v-for="(item, index) in dataSource"
				:key="index"
				ref="sliderItemRef"
				style="z-index: 66"
				:class="{ actived: currentValue === item[propsAttr.value] }"
				@click="changeSlide(index, item[propsAttr.value])"
			>
				{{ item[propsAttr.label] }}
			</span>
		</div>
	</div>
</template>
<script setup lang="ts">
/**
 * 这是 滑动切换组件
 */
import { ref, computed, watch } from "vue";
type Props = {
    modelValue?: any; // 数值
	dataSource: any[]; // 数据源
	propsObj?: { [key: string]: any }; // 读取的字段属性
    animation?: boolean; // 是否开启动画
    duration?: number; // 动画时长 注意单位为毫秒 
};
const props = withDefaults(defineProps<Props>(), {
	modelValue: null,
	dataSource: () => [],
	propsObj: () => {
		// 属性
		return {};
	},
	animation: true,
  duration: 500
});
const emit = defineEmits(["update:modelValue", "change"]);

const propsAttr = computed(() => {
	const obj = {
		label: "label",
		value: "value"
	};
	return Object.assign(obj, props.propsObj);
});

const sliderItemRef = ref(); // slider下的每个item实例
const currentValue = ref(props.modelValue); // 记录当前激活的值
const sliderOffsetLeft = ref("0"); // 记录滑块需要滑动的距离

// 用于在slider滑块上展示的文案--这个文案的作用主要是撑开slider滑块的宽度
const showSliderName = computed(() => {
	const target = props.dataSource.find((item: any) => item[propsAttr.value.value] === currentValue.value);
	return target[propsAttr.value.label];
});
// 滑块的动画时常
const sliderDuration = computed(() => {
  return (props.duration / 1000) + "s";
})

// 监听激活的值的变化发射事件
watch(
	() => currentValue.value,
	() => {
		emit("update:modelValue", currentValue.value);
	},
	{ immediate: true }
);

// 切换滑块
const changeSlide = (index: number, value: any) => {
	const offset = 2; // 偏移量
  // 更改滑块 滑动的距离
	sliderOffsetLeft.value = sliderItemRef.value[index].offsetLeft - offset + "px";
  // 记录当前激活的值
	currentValue.value = value;
	emit("change", value);
};
</script>

<style scoped lang="scss">
.container {
  position: relative;
	display: inline-flex;
	align-items: center;
	padding: 3px;
	overflow: hidden;
	background: rgba($color: #000000, $alpha: 10%);
	border-radius: 20px;
	span {
		display: inline-block;
		padding: 2px 24px;
		font-size: 12px;
		color: ##606266;
		cursor: pointer;
	}
	.slider {
		position: absolute;
		display: inline-block;
		transform: translateX(v-bind(sliderOffsetLeft));
		overflow: hidden;
		color: transparent;
		background-color: ##409EFF;
		border-radius: 20px;
	}
  .is-transition {
    transition: all v-bind(sliderDuration);
  }
	.actived {
		z-index: 99;
		font-weight: 600;
		color: #ffffff;
		border-radius: 20px;
	}
}
</style>

在文件中使用滑动切换组件

<template>
	<div>
		<h2>滑动切换组件</h2>
		<CSlideSwitch v-model="slideValue" :data-source="btnList" />
		<div>绑定的值:{{ slideValue }}</div>
	</div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import CSlideSwitch from "@/components/modules/CSlideSwitch/index.vue";

const btnList = [
	{ label: "今天", value: "today" },
	{ label: "昨天", value: "yesterday" },
	{ label: "本周", value: "this_week" },
	{ label: "上周", value: "last_week" },
	{ label: "本月", value: "this_month" },
	{ label: "上月", value: "last_month" }
];

const slideValue = ref("today");
</script>

~~END~~

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue实现顶部滑动切换菜单效果,可以通过以下步骤实现: 1. 首先,我们需要创建一个Vue组件来表示菜单。可以使用`v-for`指令循环渲染菜单选项,并通过`v-bind`绑定`isActive`属性来控制当前选中的菜单项。同,设置一个`@click`事件监听器,使得点击菜单项可以切换选中的项。 2. 在样式上,可以使用CSS来控制菜单项的样式,使得被选中的项可以突出显示。 3. 接下来,我们需要监控滚动事件。可以使用`window`对象的`scroll`事件,并将其绑定到一个滚动事件处理函数上。 4. 在滚动事件处理函数中,通过获取`window.pageYOffset`属性来获取当前滚动的位置。然后,计算出每个菜单项距离顶部的距离,与当前滚动位置进行比较。以此来判断当前应该激活哪个菜单项。 5. 最后,通过将`isActive`属性绑定到菜单项的样式上,以实现滚动切换菜单的效果。 综上所述,以上步骤可以实现Vue中顶部滑动切换菜单效果实现。具体代码请参考以下示例: ``` <template> <div> <ul> <li v-for="(item, index) in menuItems" :key="index" :class="{ active: item.isActive }" @click="setActive(index)"> {{ item.title }} </li> </ul> </div> </template> <script> export default { data() { return { menuItems: [ { title: '菜单1', isActive: false }, { title: '菜单2', isActive: false }, { title: '菜单3', isActive: false }, ], } }, mounted() { window.addEventListener('scroll', this.handleScroll) }, destroyed() { window.removeEventListener('scroll', this.handleScroll) }, methods: { setActive(index) { this.menuItems.forEach((item, i) => { item.isActive = i === index }) }, handleScroll() { const scrollY = window.pageYOffset const menuItems = this.$refs.menuItems menuItems.forEach((item, index) => { const rect = item.getBoundingClientRect() const offsetTop = rect.top + scrollY this.menuItems[index].isActive = scrollY >= offsetTop && scrollY < offsetTop + rect.height }) }, }, } </script> <style> .active { /* 设置选中菜单项的样式 */ background-color: #ccc; } </style> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值