vue3+ts实现仿微信通讯录A-Z排序以及导航栏的功能

文章目录


前言

需要实现一个通讯录的功能很简单,只需要在后端将用户名查询出来返回给前端展示就好,但是要按照A-Z排序就稍稍复杂了一点,要考虑用户名为中文、英文、数字等特殊字符的如何进行排序,仿照微信的话,数字以及特殊字符的归于‘#’类,排在最后。


提示:以下是本篇文章正文内容,下面案例可供参考

一、pinyin4j是什么?

是一个Java库,用于汉字转拼音,核心就是PinyinHelper类,感兴趣可以上官网研究pinyin4j, a Java library converting Chinese to pinyin

二、使用步骤

1.引入库

代码如下(示例):

<dependency>
    <groupId>com.belerweb</groupId>
    <artifactId>pinyin4j</artifactId>
    <version>2.5.1</version>
</dependency>

2.后端代码

逻辑:输出A-Z,(char) (96 + i)将数字i转换为对应的字符,其中96是字符'a'的ASCII值。然后,String.valueOf()将字符转换为字符串,并且.toUpperCase()将字符串中的第一个字符转换为大写。循环遍历数据库查询出来的用户list集合,判断一下第一个字符是否为中文或者英文,获取对应字符的拼音,判断该用户是否在A-Z的范围中,将数据封装成一个json格式。

代码如下(示例):

 /**
     * 按用户拼音首字母分组
     * @param list
     * @return
     * @throws BadHanyuPinyinOutputFormatCombination
     */
    public static List<String> getUserCodeGroup(List<Member> list) throws BadHanyuPinyinOutputFormatCombination {
        //输出26个字母
        JSONObject jsonObj = new JSONObject();
        List<String> jsonList= new ArrayList();
        List<Member> otherLetter = new ArrayList<Member>();
        for(int i=1;i<=26;i++){
            String word = String.valueOf((char) (96 + i)). toUpperCase();
            //循环找出首字母一样的数据
            List<Member> letter = new ArrayList<Member>();
            otherLetter = new ArrayList<Member>();
            for (Member str : list) {

                    if(isChineseFrist(str.getName().charAt(0)) || isEnglishFrist(str.getName())) {//判断用户名的第一个字母是否为中文或者字母
                        String code = changeChinesePinyin(str.getName()).get("groupPinyin");
                        if (word.equals(code)) {
                            letter.add(str);
                        }
                        System.out.println(str);
                    }else{//非英文或中文的用户名 排最后
                        otherLetter.add(str);
                    }
                }

            //因前端需要json格式的数据进行遍历,所以此处我把数据封装成json格式
            jsonObj.put("key",word);
            jsonObj.put("list",letter);

            jsonList.add(jsonObj.toString());

        }
        jsonObj.put("key","#");
        jsonObj.put("list",otherLetter);

        jsonList.add(jsonObj.toString());

        return jsonList;
    }


  /**
     *获取拼音的工具类
     * 获取姓名全拼和首字母
     * @param  chinese 汉语名称
     * @return fullPinyin : 全拼        simplePinyin : 首字母  groupPinyin:微信用户组第一个字母
     * @throws BadHanyuPinyinOutputFormatCombination
     */
    public static Map<String, String> changeChinesePinyin(String chinese) throws BadHanyuPinyinOutputFormatCombination {
        Map<String, String> pinyin = new HashMap<String, String>();

        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        format.setVCharType(HanyuPinyinVCharType.WITH_V);

        StringBuffer fullPinyin = new StringBuffer();
        StringBuffer simplePinyin = new StringBuffer();
        StringBuffer firstPinyin = new StringBuffer();
        char[] chineseChar = chinese.toCharArray();
        //判断如果是英文就不需要去获取拼音直接返回英文就可以了
        if(isEnglishFrist(chinese)){
            fullPinyin = fullPinyin.append(chinese);
            simplePinyin = simplePinyin.append(chinese);
            firstPinyin=firstPinyin.append(chineseChar[0]);
        }
       //判断如果是中文就需要去获取拼音直接返回英文就可以了
        if(isChineseFrist(chinese)){
        for (int i = 0; i < chineseChar.length; i++) {
            String[] str = null;
            try {
                str = PinyinHelper.toHanyuPinyinStringArray(chineseChar[i],
                        format);
            } catch (BadHanyuPinyinOutputFormatCombination e) {
                e.printStackTrace();
            }
            if (str != null) {
                fullPinyin = fullPinyin.append(str[0].toString());
                simplePinyin = simplePinyin.append(str[0].charAt(0));

            }
            if (str == null) {
                String regex = "^[0-9]*[a-zA-Z]*+$";
                Pattern pattern = Pattern.compile(regex);
                Matcher m = pattern.matcher(String.valueOf(chineseChar[i]));
                if (m.find()) {
                    fullPinyin = fullPinyin.append(chineseChar[i]);
                    simplePinyin = simplePinyin.append(chineseChar[i]);
                }
            }
        }
        String[] name = PinyinHelper.toHanyuPinyinStringArray(chineseChar[0],format);
        firstPinyin=firstPinyin.append(name[0].charAt(0));
        }

        pinyin.put("fullPinyin", fullPinyin.toString());
        pinyin.put("simplePinyin", simplePinyin.toString().toUpperCase());
        pinyin.put("groupPinyin", firstPinyin.toString().toUpperCase());
        return pinyin;
    }
 /**
     * 判断第一个是否为字母
     * @param str
     * @return
     */
    public static boolean isEnglishFrist(String str){
        for (int i = str.length();--i>=0;){
            if (Character.isLetter(str.charAt(i))){
                return true;
            }
        }
        return false;
    }
 /**
     * 判断第一个是否为中文
     * @param str
     * @return
     */
    public static boolean isChineseFrist(char ch) {
        return Character.UnicodeBlock.of(ch) == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || Character.UnicodeBlock.of(ch) == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS;
    }

3.前端vue3+ts代码

<template>

  <!-- 通讯录列表 -->
  <div class="peoBox">
    <!-- 字母检索 -->
    <div class="letter">
      <div v-for="(item, index) in navArray" :key="index" @click="scrollOn(item.key)">
        {{ item.key }}
      </div>
    </div>

    <div class="peo" ref="box">
      <div v-for="item in peoArray" :key="item.key">

        <p class="peoKey" :id="'peo' + item.key">{{ item.key }}</p>
        <li class="peolist" v-for="ele in item.list" :key="ele.name" :id="ele.name"
          @mousemove="handleMouseMove(ele.name)" @mouseleave="handleMouseLeave(ele.name)">

          <a-avatar shape="square" :src=ele.avatar alt="用户头像">
            <template #icon>
              <UserOutlined />
            </template>
          </a-avatar>

          {{ ele.name }}
        </li>
      </div>
    </div>

  </div>
</template>
<script lang="ts">
import { defineComponent, reactive } from 'vue';
import { getAddressBookList } from '@/api/system/addressBook'

const handleMouseMove = (name) => {
  var addressList = document.getElementById(name);
  if (null != addressList)
    addressList.style.backgroundColor = '#e7e7e7'
}
const handleMouseLeave = (name) => {
  var addressList = document.getElementById(name);
  if (null != addressList)
    addressList.style.backgroundColor = 'white'
}

const peoArray: any = reactive([])
const navArray: any = reactive([])
const initData = () => {
  getAddressBookList().then(res => {
    debugger
    const data = res.data;
    data.forEach((ele) => {
      ele = JSON.parse(ele)
      navArray.push(ele)
      if (ele.list.length > 0) {
        peoArray.push(ele)
      }

    });
  })
}
initData()

const scrollOn = (key) => {
  let target = document.getElementById("peo" + key); //获取每个字母通讯录对象
  
  if (target){
    target.scrollIntoView({
      behavior: "smooth", // 定义动画过渡效果, "auto"或 "smooth" 之一。默认为 "auto"
    });
    
  }
   
   
}

export default defineComponent({
  setup() {
    return {
      peoArray,
      navArray,
      handleMouseMove,
      handleMouseLeave,
      navBar: true,
      navBarHeight: "50px", //导航栏高度
      scrollOn,
    };
  },
});

</script>
<style scoped>
.peoBox {
  position: relative;
  background-color: white;
  color: black;
}

.peoKey {
  margin-bottom: -5px;
  color: #909499;
}

.peolist {
  height: 55px;
  padding-top: 12px;
}

.peoHr {
  border-bottom: 1px solid #f7f7f7f7;
}

/* 字母 */
.letter {
  position: absolute;
  right: 10px;
  top: 25%;
  z-index: 2;
}
</style>

效果图,点击右边的导航栏会调转到对应的用户列表。

总结

刚学vue3+ts,代码不规范的地方请谅解,也可以帮忙修改完善一下~

相互学习进步

参考文档:

封装一个类似微信通讯录带有字母检索功能的vue组件_vue 前端 通讯录-CSDN博客Java获取名字首字母拼音及用户按名字拼音分组工具_java中将名字首字符按26个字母分组-CSDN博客

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在 Vue3 + TypeScript + Vite 中使用 `credit-card-type` 库,可以按照以下步骤进行: 1. 安装 `credit-card-type`: ```bash npm install credit-card-type --save ``` 2. 创建一个 `.d.ts` 文件来声明 `credit-card-type` 模块: ```typescript // credit-card-type.d.ts declare module 'credit-card-type' { export interface CreditCardTypeInfo { niceType: string; type: string; patterns: number[][]; gaps: number[]; lengths: number[]; code: { name: string; size: number; }; } export function getTypeInfo(cardNumber: string): CreditCardTypeInfo[]; export default function(cardNumber: string): CreditCardTypeInfo[]; } ``` 3. 在 Vue 组件中导入并使用 `credit-card-type`: ```typescript <template> <div> <input v-model="cardNumber" /> <div v-if="cardType"> Card type: {{ cardType.niceType }} </div> </div> </template> <script lang="ts"> import { defineComponent, ref } from 'vue'; import creditCardType from 'credit-card-type'; export default defineComponent({ setup() { const cardNumber = ref(''); const cardType = ref(null); const updateCardType = () => { const result = creditCardType(cardNumber.value); cardType.value = result[0]; }; return { cardNumber, cardType, updateCardType, }; }, watch: { cardNumber: { handler: 'updateCardType', }, }, }); </script> ``` 在这个例子中,我们使用 `credit-card-type` 库来检测信用卡类型,每当输入框中的卡号发生变化时,就会触发 `updateCardType` 方法来更新卡类型。最后,我们将卡类型显示在模板中。 希望这个例子能够帮助你在 Vue3 + TypeScript + Vite 中使用 `credit-card-type` 库。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值