需求场景
项目开发中对方要求手机号带上全球区号
需求分析
项目使用的是若依前端框架,element-ui的框架。尝试使用已经网上的组件vue-country-intl等发现不怎么适配element-ui的样式等。这还不是关键的,关键的是弹窗中使用这些组件发现区号的下拉展示框展示不全,层级存在问题,设置css的z-index等相关属性也不能有效处理。于是决定手搓一个element-ul下拉的区号,支持国际化,支持中英文搜索过滤,支持自定义label展示,样式自己还能修改。
效果展示
英文(国际化)
中文
代码实现
组件代码
涉及整个组件代码(国家区号json、国旗)已上传到这里:
element-ui风格下拉手机区号组件资源-CSDN文库
主要代码index.vue
<template>
<div >
<el-select v-model="currentCode"
filterable :filter-method="dataFilter"
@visible-change="visibleChange"
:placeholder="$t(placeholder)"
@change="setCountryCode"
style="width:100%">
<el-option
v-for="dict in countryList"
:key="dict.code"
:label="`+${dict.dialCode}` "
:value="dict.dialCode"
>
<template v-if="currentUseChinese" #default>
<div v-if="showFlag" :class="['flag', `flag-${dict.code}`]"></div>
{{dict.CNName}} +{{dict.dialCode}}
</template>
<template v-else #default>
<div v-if="showFlag" :class="['flag', `flag-${dict.code}`]"></div>
{{dict.name}} +{{dict.dialCode}}
</template>
</el-option>
</el-select>
</div>
</template>
<script>
import countryListData from '../VueCountryCodeSelector/assets/countryData.json'
import Cookies from "js-cookie";
export default {
name: 'countryCodeSelector',
props: {
// placeholder显示内容
placeholder: {
type: String,
default: "区号",
},
// 是否显示国旗
showFlag: {
type: Boolean,
default: true,
},
/*
* @description 国际区号
* */
countryCode: {
type: String,
default: null
}
},
data () {
return {
currentCode: this.countryCode?Number(this.countryCode):null,
countryList: []
}
},
computed: {
// 根据props传过来的国际区号检索出所在的整个对象
currentData () {
return this.countryList.filter((item) => {
return Object.keys(item).some((key) => {
return item[key] === this.currentCode
})
})[0]
},
currentUseChinese(){
let lg = Cookies.get('language') || 'zh-CN';
if('zh-CN'!==lg){
return false;
}
return true;
},
},
created() {
// 拿到JSON里面的国家区号数据并赋值到本地data中
this.countryList = countryListData
},
methods: {
// 根据输入框的内容进行模糊检索
dataFilter(val) {
//this.currentCode = val;
this.countryList = countryListData
if (val) {
this.countryList = countryListData.filter((item) => {
return Object.keys(item).some((key) => {
return String(item[key]).toLowerCase().indexOf(val.toLowerCase()) > -1
})
})
}
},
visibleChange(visible){
//这里是再次点击下拉时还原选项列表 by wu
if(visible)this.countryList = countryListData
},
setCountryCode(){
// 更改父组件的值
this.$emit('update:countryCode', this.currentCode.toString());
}
},
}
</script>
<style scoped>
@import "../VueCountryCodeSelector/assets/css/flags.css";
</style>
组件使用
//main.js引入组件
//手机区号组件
import CountryCodeSelector from "@/components/VueCountryCodeSelector";
//全局挂载
Vue.component('CountryCodeSelector', CountryCodeSelector)
......
//页面中使用
<el-form-item :label="$t('CustomerInfo.managerPhone')" prop="managerPhone">
<country-code-selector :showFlag="true" :placeholder="'CustomerInfo.managerPhoneZonePlaceholder'" :countryCode.sync="modForm.managerPhoneZone" style="width:24%;float: left"></country-code-selector>
-
<el-input v-model="modForm.managerPhone" autocomplete="off" maxlength="20" show-word-limit style="width:73%;"/>
</el-form-item>
组件参数说明
showFlag | 下拉中是否展示国旗 |
placeholder | label的国际化显示文字 |
countryCode | 页面区号字段绑定的数据 |
总结
组件优化
组件其实有更多可扩充的空间,比如选择下拉后填充到页面是只展示区号还是支持展示国旗和国家名称,用的时候修改下这里就行:
开发经验总结
开发过程中主要学习了el-select自定义label展示、自定义过滤、父子传参等知识点。
自定义label展示如上图所示。自定义过滤使用了
filterable :filter-method="dataFilter"
这里dataFilter放到method中方法,执行你所需要的过滤,在页面输入过滤条件后会自动触发这个方法,我们只需要将下拉数据列表刷新下就行了(吗?)。
这里是有个坑的,当时做了后发现输入过滤条件后是过滤到了我们需要的数据,但是此时的下拉数据列表已经发生改变,在点开下拉发现还是上次过滤的数据,这就需要一个办法还原回原来的数据,查看官方文档看到了一个参数:
使用此参数在下拉框关闭时或者打开时还原下拉数据列表:
@visible-change="visibleChange"
方法
visibleChange(visible){ //这里是再次点击下拉时还原选项列表 by wu if(visible)this.countryList = countryListData }