VUE2版本的仿微信通讯录侧滑列表

<template>
	<!-- Vue模板部分 -->
	<div>
		<div v-for="(group, index) in groupedArray" :key="index" ref="indexcatch">
			<h2>{{ letter[index] }}</h2>
			<ul>
				<li v-for="item in group" :key="item.id">
					{{ item.name }}
				</li>
			</ul>
		</div>
		<div ref="scrollDiv"
			style="position: fixed;right: 0;top: calc(50vh - 325px);width: 50px; height: 650px;background-color: #CCCCCC;"
			@click="handleClick" @mousedown="startLongPress" @mouseup="stopLongPress">
			<div v-for="(item,index) in letter" :key="index"
				:style="{textAlign: 'center',height: '25px',color:IndexItem==index?'red':'black',fontWeight:IndexItem==index?'700':''}">
				{{letter[index]}}
			</div>
		</div>
	</div>
</template>

<script>
	// yarn add js-pinyin --save 或者 npm install js-pinyin --save 安装
	// 作用是把汉字转化为拼音,以便于排序使用
	import Pinyin from 'js-pinyin'; 

	export default {
		data() {
			return {
				letter: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
					'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
				], // 右侧字母列表
				arr: [], // 被处理过的左侧数据列表数据(已经分类好)
				EleHeight: 25, // 右侧每个字母的高(使用这个高度用于计算点击的或者滚动到的是哪个索引的字母,以便于让左侧列表跟着进行滚动到指定位置)
				FatherDivHeight: -1, // 右侧字母列表的容器距离浏览器顶部的距离
				IndexItem: -1, // 用于将字母高亮显示
			};
		},
		computed: {
			groupedArray() {
				let result = {};
				// 生成随机名字的函数(这个是找GPT要的方法,你也用不上,毕竟你的项目是有数据的,这里是模拟的数据,就不写注释了)
				function getRandomName() {
					const surnames = ['张', '王', '李', '赵', '刘', '陈', '杨', '黄', '吴', '郑', '孙', '周', '徐', '朱', '高', '林', '何',
						'马', '罗', '梁', '宋', '郭', '胡', '郭', '潘', '李', '谢', '邓', '曹', '程', '曾', '彭', '蔡', '梁', '田', '许',
						'韩', '冯', '曹', '庄', '魏', '张', '石', '章', '叶', '董', '汪', '方', '于', '邹', '苏', '潘', '葛', '奚', '范',
						'彭', '郎', '鲁', '韦', '昌', '马', '苗', '凤', '花', '贾', '严', '武', '庄', '邱', '卫', '蒋', '童', '颜', '郭',
						'梅', '盛', '林', '翟', '石', '王'
					];
					const names = ['三', '四', '五', '六', '七', '八', '九', '十', '一', '二', '华', '明', '强', '超', '辉', '军', '涛',
						'勇', '毅', '伟', '刚', '强', '军', '平', '杰', '峰', '雷', '磊', '新', '洋', '宇', '昊', '翔', '晓', '亮', '云',
						'飞', '鹏', '浩', '波', '文', '轩', '东', '俊', '涵', '阳', '晨', '帆', '宇', '航', '建', '琪', '轩', '海', '立',
						'智', '志', '弘', '博', '晨', '瑞', '凯', '子', '卓', '坤', '雄', '霖', '政', '晗', '煜', '�'
					];
					let getRandomItem = (arr) => arr[Math.floor(Math.random() * arr.length)];
					let randomNames = [];
					for (let i = 0; i < 299; i++) {
						let surname = getRandomItem(surnames);
						let name = getRandomItem(names);
						randomNames.push({
							"name": surname + name
						});
					}
					return randomNames;
				}
				this.arr = getRandomName();
				this.arr.forEach(item => {
					let firstLetter = this.getFirstLetter(item.name);
					if (!result[firstLetter]) {
						result[firstLetter] = [];
					}
					result[firstLetter].push(item);
				});
				let allLetters = 'abcdefghijklmnopqrstuvwxyz'.split('');
				let groupedArray = allLetters.map(letter => result[letter] || []);
				return groupedArray;
			}
		},
		methods: {
			getFirstLetter(str) {
				// 将中文姓名转换为拼音并取首字母
				return Pinyin.getCamelChars(str).charAt(0).toLowerCase();
			},
			startLongPress(e) {
				// 鼠标按下(开始监听全局的鼠标滚动)
				this.FatherDivHeight = e.currentTarget.offsetTop // 获取当前字母容器距离顶部的距离
				// 添加全局事件监听器
				document.addEventListener('mousemove', this.handleScroll);
			},

			stopLongPress() {
				// 移除全局事件监听器(鼠标抬起移除全局的鼠标移动事件)
				document.removeEventListener('mousemove', this.handleScroll);
			},
			handleClick(event) {
				// 点击滚动实现
				// 获取当前滚动的y坐标
				// console.log(event.y);
				// 获取当前字母列表每个字母的高度
				// console.log(this.EleHeight);
				// 计算当前字母索引
				let index = Math.ceil((event.detail.y - this.FatherDivHeight) / this.EleHeight) - 1;
				console.log(index);
				// 将当前索引赋值
				this.IndexItem = index
				// 将右侧列表滚动到相应位置
				scrollTo({
					left: 0, // 距离左侧距离
					top: this.$refs.indexcatch[index].offsetTop, //点击侧边栏的哪个索引就让右侧哪个索引对应的块滚动
					behavior: "smooth", // 点击滚动这里我用了平滑滚动,带动画的
				})
			},

			handleScroll(event) {
				// 获取当前滚动的y坐标
				// console.log(event.y);
				// 获取当前字母列表每个字母的高度
				// console.log(this.EleHeight);
				// 计算当前字母索引
				let index = Math.ceil((event.y - this.FatherDivHeight) / this.EleHeight) - 1;
				console.log(index);
				// 将当前字母索引赋值
				this.IndexItem = index
				// 将右侧列表滚动到相应位置
				scrollTo({
					left: 0,
					top: this.$refs.indexcatch[index].offsetTop, //点击侧边栏的哪个索引就让右侧哪个索引对应的块滚动
					behavior: "auto", // auto 瞬间滚动 无动画 smooth 平滑滚动带有动画效果
				})
			}
		}
	};
</script>

效果图
在这里插入图片描述
支持滑动和点击

Vue3是一个流行的前端框架,它主要用于构建用户界面,特别是单页面应用(SPA)。如果你想仿微信聊天界面,可以利用Vue3的组件化思想、虚拟DOM以及Vuex状态管理库来实现: 1. **布局设计**:创建一个包含消息列表和输入框的主容器,使用`v-for`遍历消息数组并展示聊天记录,每个消息作为独立的组件(比如MessageCard.vue),包含发送者信息、时间戳和消息内容。 ```html <template> <div> <message-card v-for="(msg, index) in messages" :key="index"></message-card> <input-chat @send="onSend" /> </div> </template> <script> import MessageCard from './MessageCard.vue'; export default { components: { MessageCard }, data() { return { messages: [], // 存储聊天记录的数组 }; }, methods: { onSend(text) { // 发送新消息的逻辑 } } }; </script> ``` 2. **MessageCard组件**:显示具体的聊天信息,包含接收方头像、昵称、文字消息等,并可能添加表情、图片等扩展功能。 3. **InputChat组件**:用于输入文本,监听用户的输入事件,当用户按下Enter键或者点击发送按钮时触发`@send`自定义事件,传递新消息内容给父组件。 4. **Vuex管理状态**:如果需要保存用户的登录状态或者会话历史,可以使用Vuex存储数据,保持状态的统一和更新的同步。 5. **样式处理**:使用CSS或者CSS预处理器(如Sass或Less)来设计聊天窗口的样式,包括气泡形状、滚动条、动画效果等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萧寂173

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值