【全栈实战】基于 Vue3 + Wot Design Uni 动手封装组件
😊你好,我是小航,一个正在变秃、变强的文艺倾年。
😊好久没有更新有关前端实战教程了,本文主要讲解【全栈实战】基于 Vue3 + Wot Design Uni 动手封装组件!
😊这个教程你将会学到技术正确的选型、Vue3基础语法实践、父子组件传参、移动端组件封装、组件源码阅读技巧、小程序适配技巧等,一起卷起来吧!
目录
- 一、前言
- Wot Design Uni
- 技术选型
- UI库选型
- 开源热度对比
- 多端支持情况
- 组件数量
- ts 支持情况
- 发展趋势
- Tyme
- 语言支持情况
- 活跃程度
- 发展趋势
- 使用教程
- 二、封装
- 思路
- 父组件
- 子组件
- 初始化
- 样式搭建
- 工具封装
- 常量定义
- 逻辑设计
- 解决微信小程序 Tab 动画异常
- 效果展示
- 三、完整代码
- 代码
- 下一步建议
一、前言
由于本人近期需要一个支持输入农历、公历的移动端组件
,仅需要输入年、月、日、时,输入界面要求可以同时选择四列,且自由切换农历、公历。网上没找到现成的组件,只好自己封装一个了。下面先介绍一下自己的技术选型,本人开发采用的语言是Vue3 + Typescript
。
Wot Design Uni
技术选型
Uniapp的上手难度很低,而且Uniapp的语法风格与Vue保持高度一致,可以直接复用已有的Vue项目中的代码和经验。因此我这里使用的开发框架是Uniapp。
UI库选型
对于UI库的选型,我们常常从开源热度、多端支持情况、组件数量、ts支持情况、发展趋势来选择。
开源热度对比
截止到 2024-05-30
发表文章时的数据:
UI 框架 | uv-ui | uview-plus | wot-ui | TuniaoUI |
---|---|---|---|---|
github stars | 568 | 362 | 492 | 192 |
gitee stars | 555 | 126 | 35 | - |
github forks | 1.1k | 158 | 188 | 20 |
gitee forks | 75 | 4 | 30 | - |
实到这里就一决高下了,github star 数
: uv-ui(568)
> wot-ui(492)
> uview-plus(362)
> TuniaoUI(192)
,其中 uv-ui
和 wot-ui
拔得头筹。
多端支持情况
UI 框架 | uv-ui | uview-plus | wot-ui | TuniaoUI |
---|---|---|---|---|
h5 | ✅ | ✅ | ✅ | ✅ |
app(ios) | ✅ | ✅ | ✅ | ✅ |
app(android) | ✅ | ✅ | ✅ | ✅ |
微信小程序 | ✅ | ✅ | ✅ | ✅ |
支付宝小程序 | ✅ | ✅ | ✅ | ✅ |
QQ 小程序 | ✅ | ✅ | ❌ | ❌ |
百度小程序 | ✅ | ✅ | ❌ | ❌ |
头条小程序 | ✅ | ✅ | ❌ | ❌ |
组件数量
UI 框架 | uv-ui | uview-plus | wot-ui | TuniaoUI |
---|---|---|---|---|
总数 | 67 | 67 | 71 | 55 |
基础组件 | 8 | 11 | 8 | 5 |
表单组件 | 16 | 17 | 20 | 14 |
数据组件 | 13 | 4 | 18 | 4 |
反馈组件 | 8 | 10 | 16 | 8 |
布局组件 | 7 | 9 | - | 8 |
导航组件 | 8 | 8 | 9 | 5 |
其他组件 | 7 | 8 | - | 5 |
内容组件 | - | - | - | 6 |
组件数:wot(71)
> uv-ui(67)
= uview-plus(67)
> TuniaoUI(55)
ts 支持情况
查看 4 个组件库的源码,可以了解到:
uv-ui
和uView-plus
都是js
写的,并非ts
,可以通过ttou/uv-typings
提供类型支持。wot
和TuniaoUI
都是ts
写的,编码体验会好很多。
小知识:代码里如何辨别一个库是否有 ts 支持,写代码的时候按 ctrl + i
(Mac 里 cmd + i
),如果有提示就是有,啥都没有就是没有。
举个例子,编写 <xx-button type="" ...
,在 type=""
双引号里面按 ctrl + i
,看提示就知道了。
wot
有提示
uv-ui
无提示
发展趋势
wot-ui和
uv-ui皇城
PK
目前 wot-ui
还是比不过 uv-ui
的,但是 wot-ui
有反超的势头。
这里我选择了wot-ui。wot-ui 全称 wot-design-uni,是 wot-design 的 uniapp 版本,文档地址:https://wot-design-uni.netlify.app/
Tyme
Tyme是一个非常强大的日历工具库,可以看作 Lunar 的升级版,拥有更优的设计和扩展性,支持公历和农历、星座、干支、生肖、节气、法定假日等。这有助与我们进行农历和公历之间的转化。
开源地址:https://github.com/6tail/tyme4ts
语言支持情况
看着就很棒,支持了市面了主流的语言。
活跃程度
近两周刚更新源代码,说明出了问题能解决。我们在采用别人封装好的库时候,一定要多看看仓库活跃程度,如果这个仓库都好久没有更新维护了,不建议使用。
发展趋势
没毛病,就它了!
使用教程
// install
npm init -y
npm i typescript -D
npm i ts-node -D
npm i tyme4ts
// test.ts
import {SolarDay} from 'tyme4ts';
const solar: SolarDay = SolarDay.fromYmd(1986, 5, 29);
// 1986年5月29日
console.log(solar.toString());
// 农历丙寅年四月廿一
console.log(solar.getLunarDay().toString());
// run
ts-node test.ts
二、封装
思路
示例数据:
// 公历2024年12月22日13时
birthdayValue: [2024, 12, 22, 13, 1]
用到的组件:
Input、Picker、Popup
父组件
<birthdayPicker
v-model="state.userInfo.birthdayValue"
prop="birthdayValue"
:rules="[
{
required: false,
message: '请输入生辰',
},
]"
></birthdayPicker>
// 定义变量
const state = reactive({
// 用户信息数据
userInfo: {
birthdayValue: null,
},
})
子组件
初始化
Tips:便于调试,推荐onload加入debugger,可以直接看到小程序源代码是否刷新,小程序经常不刷新代码,经常误认为自己的编码问题,也是比较恼火。
onLoad(() => {
debugger
})
定义组件名称
defineOptions({
name: 'birthdayPicker',
})
定义接收父组件传值的接口
type bithdayPickerProps = {
modelValue: number[] // 生日值
disabled?: boolean // 是否禁用
prop: string // 表单域 model 字段名,在使用表单校验功能的情况下,该属性是必填的
rules: FormItemRule[] // 表单校验规则
}
const props = defineProps<bithdayPickerProps>()
const emit = defineEmits(['update:modelValue'])
定义用到的状态变量
const state = reactive({
displayColumns: [],
popupShow: false,
birthdayArr: ['农历', '公历'],
birthday: [],
birthdayIndex: 0,
pickerViewLoaded: false,
})
// 计算Picker展示值
const displayBirthday = computed(() => {
const birthday = state.birthday
// 避免空数组调用join函数
if (isNullBirthdayArray(birthday, 4)) return null
// 公历2024年12月22日13时
return (
state.birthdayArr[state.birthdayIndex] +
birthday[0] +
'年' +
findValueInCoulums(birthday[1], state.displayColumns[1]) +
findValueInCoulums(birthday[2], state.displayColumns[2]) +
birthday[3] +
'时'
)
})
这里有个常见的面试考点:
如何在 ref() 与 reactive() 之间做正确选择?
(1)ref() 和 reactive() 用于跟踪其参数的更改。当使用它们初始化变量时,是向 Vue 提供信息:“嘿,每次这些变量发生更改时,请重新构建或重新运行依赖于它们的所有内容”。
(2)ref() 函数可以接受原始类型(最常见的是布尔值、字符串和数字)以及对象作为参数,而 reactive() 函数只能接受对象作为参数。
(3)ref() 有一个 .value 属性,你必须使用 .value 属性获取内容,但是使用 reactive() 的话可以直接访问。
(4)使用 ref() 函数可以替换整个对象实例,但是在使用 reactive() 函数时就不行。
(5)如果你喜欢组件内部状态仅有一个变量,那么 reactive() 就是适合你的正确工具。本人更喜欢使用reactive,看着比较舒服。
样式搭建
编写组件样式:
<template>
<wd-popup
v-model="state.popupShow"
position="bottom"
custom-style="border-radius:32rpx;height: 300px;"
:close-on-click-modal="false"
@close="closeBirthdayPicker"
closable
@after-enter="handleOpened"
>
<wd-tabs v-model="state.birthdayIndex" animated swipeable ref="tabsRef" @change="onChangeTab">
<wd-tab v-for="(item, index) in state.birthdayArr" :key="index" :title="item">
<wd-picker-view
:columns="state.displayColumns"
v-model="state.birthday"
:column-change="onChangeColumn"
ref="birthdayPicker"
/>
</wd-tab>
</wd-tabs>
</wd-popup>
<div @click="openBirthdayPicker">
<wd-input
:prop="props.prop"
:rules="props.rules"
type="text"
label="生辰"
v-model="displayBirthday"
placeholder="请选择"
readonly
required
placeholder-style="color:#bfbfbf"
>
<template #suffix>
<!--箭头-->
<wd-icon name="arrow-right" color="rgba(0, 0, 0, 0.25)" size="18px" />
</template>
</wd-input>
</div>
</template>
基础的打开、关闭
// 打开生日选择器
const openBirthdayPicker = () => {
if (props.disabled) return
state.popupShow = true
const value = props.modelValue
if (isNullBirthdayArray(value, 5)) {
state.birthday = [1940, 1, 1, 1]
state.birthdayIndex = 0
return
}
state.birthday = [value[0], value[1], value[2], value[3]]
state.birthdayIndex = value[4]
}
// 关闭生日选择器
const closeBirthdayPicker = () => {
emit('update:modelValue', [...state.birthday, state.birthdayIndex])
state.popupShow = false
}
工具封装
由于我这里会经常对bithday数组进行判空,判断依据有:是否有空值、长度是否满足,是否是数组等,这里我们封装成一个函数
const isNullBirthdayArray = (birthday: number[], validLength: number = birthday.length) => {
return (
!birthday ||
(isArray(birthday) &&
(!birthday.length ||
birthday.length !== validLength ||
birthday.every((item) => item === null)))
)
}
Picker值展示时需要根据birthday的值进行与当前columns映射
const findValueInCoulums = (value: number, columns: any[]) => {
let res = ''
columns.forEach((item) => {
if (item.value === value) res = item.label
})
return res
}
常量定义
// 定义农历月份和日期的汉字表示
const chineseMonths = [
'一月',
'二月',
'三月',
'四月',
'五月',
'六月',
'七月',
'八月',
'九月',
'十月',
'十一月',
'十二月',
]
const chineseDays = [
'初一',
'初二',
'初三',
'初四',
'初五',
'初六',
'初七',
'初八',
'初九',
'初十',
'十一',
'十二',
'十三',
'十四',
'十五',
'十六',
'十七',
'十八',
'十九',
'二十',
'廿一',
'廿二',
'廿三',
'廿四',
'廿五',
'廿六',
'廿七',
'廿八',
'廿九',
'三十',
]
根据常量来更新展示列信息:
const yearColumns = Array.from({ length: new Date().getFullYear() - 1940 + 1 }, (_, i) => {
return { label: `${1940 + i}`, value: 1940 + i }
})
const hourColumns = Array.from({ length: 24 }, (_, i) => ({
label: `${i + 1}时`,
value: i + 1,
}))
const initDays = (len: number, type: 'lunar' | 'gregorian') =>
Array.from({ length: len }, (_, i) => {
return {
label: type === 'lunar' ? `${chineseDays[i]}` : `${i + 1}日`,
value: i + 1,
}
})
const updateColumns = (birthday: number[]) => {
let monthColumns = []
let dayColumns = []
const [_year, _month, _day, _hour, birthdayIndex] = birthday
// 1.农历列
if (birthdayIndex === 0) {
const lunarYear: LunarYear = LunarYear.fromYear(_year)
monthColumns = lunarYear.getMonths().map((month) => ({
label: month.isLeap()
? `闰${chineseMonths[month.getMonth() - 1]}`
: chineseMonths[month.getMonth() - 1],
value: month.getMonthWithLeap(),
}))
const lunarMonth: LunarMonth = LunarMonth.fromYm(_year, _month)
const dayCount: number = lunarMonth.getDayCount()
dayColumns = initDays(dayCount, 'lunar')
}
// 2.公历列
if (birthdayIndex === 1) {
monthColumns = Array.from({ length: 12 }, (_, i) => {
return { label: `${chineseMonths[i]}`, value: i + 1 }
})
const solarMonth: SolarMonth = SolarMonth.fromYm(_year, _month)
const dayCount: number = solarMonth.getDayCount()
dayColumns = initDays(dayCount, 'gregorian')
}
state.displayColumns = [yearColumns, monthColumns, dayColumns, hourColumns]
}
逻辑设计
初始化列
// 1.初始化
onMounted(() => {
handleShowValueUpdate(props.modelValue)
})
// 2.监听父组件的值变化
watch(
() => props.modelValue,
(newValue) => {
handleShowValueUpdate(newValue)
},
)
// 3.值变更时更新显示内容
const handleShowValueUpdate = (value: number[]) => {
// 0.校验
if (isNullBirthdayArray(value, 5)) {
// 更新为初始值,状态值保持不变
updateColumns([1940, 1, 1, 1, 0])
return
}
// 1.获取选中项
state.birthday = [value[0], value[1], value[2], value[3]]
state.birthdayIndex = value[4]
// 2.更新列
updateColumns(value)
}
// 4.当农历、公历切换时:
const onChangeTab = (index) => {
state.pickerViewLoaded = true
const [_year, _month, _day, _hour] = state.birthday
// 1.农历转公历
if (index.name === 1) {
console.log('农历转公历前', index.name, state.birthday)
const lunarHour = LunarHour.fromYmdHms(_year, _month, _day, _hour, 0, 0)
const solarTime: SolarTime = lunarHour.getSolarTime()
state.birthday = [
solarTime.getYear(),
solarTime.getMonth(),
solarTime.getDay(),
solarTime.getHour(),
]
console.log('农历转公历后', index.name, state.birthday)
}
// 2.公历转农历
if (index.name === 0) {
console.log('公历转农历前', index.name, state.birthday)
const solarTime = SolarTime.fromYmdHms(_year, _month, _day, _hour, 0, 0)
const lunarHour = solarTime.getLunarHour()
state.birthday = [
lunarHour.getYear(),
lunarHour.getMonth(),
lunarHour.getDay(),
lunarHour.getHour(),
]
console.log('公历转农历后', index.name, state.birthday)
}
// 3.更新Columns列,注意此时state.birthdayIndex还未更新
updateColumns([...state.birthday, index.name])
}
// 5.更新列
const updateColumns = (birthday: number[]) => {
let monthColumns = []
let dayColumns = []
const [_year, _month, _day, _hour, birthdayIndex] = birthday
// 1.农历列
if (birthdayIndex === 0) {
const lunarYear: LunarYear = LunarYear.fromYear(_year)
monthColumns = lunarYear.getMonths().map((month) => ({
label: month.isLeap()
? `闰${chineseMonths[month.getMonth() - 1]}`
: chineseMonths[month.getMonth() - 1],
value: month.getMonthWithLeap(),
}))
const lunarMonth: LunarMonth = LunarMonth.fromYm(_year, _month)
const dayCount: number = lunarMonth.getDayCount()
dayColumns = initDays(dayCount, 'lunar')
}
// 2.公历列
if (birthdayIndex === 1) {
monthColumns = Array.from({ length: 12 }, (_, i) => {
return { label: `${chineseMonths[i]}`, value: i + 1 }
})
const solarMonth: SolarMonth = SolarMonth.fromYm(_year, _month)
const dayCount: number = solarMonth.getDayCount()
dayColumns = initDays(dayCount, 'gregorian')
}
state.displayColumns = [yearColumns, monthColumns, dayColumns, hourColumns]
}
当用户滑动列后进行更新picker
const onChangeColumn = (pickerView, value, columnIndex, resolve) => {
// debugger
// 1.更新birthday值
const item = value[columnIndex]
state.birthday[columnIndex] = Number(item.value)
// 2.滑动列后重置后面的列
for (let i = columnIndex + 1; i < 4; i++) {
state.birthday[i] = 1
}
// 3.更新Columns列
updateColumns([...state.birthday, state.birthdayIndex])
// 4.更新pickerView
if (columnIndex === 0) {
pickerView.setColumnData(1, state.displayColumns[1])
pickerView.setColumnData(2, state.displayColumns[2])
pickerView.setColumnData(3, state.displayColumns[3])
} else if (columnIndex === 1) {
pickerView.setColumnData(2, state.displayColumns[2])
pickerView.setColumnData(3, state.displayColumns[3])
} else if (columnIndex === 2) {
pickerView.setColumnData(3, state.displayColumns[3])
}
// 5.更新pickerView组件
resolve()
}
这里我进行了后列重置,避免出现后面的日期不存在于当月,造成列Index错误。
解决微信小程序 Tab 动画异常
// 解决微信小程序Tabs表现异常
const tabsRef = ref<TabsInstance>()
function handleOpened() {
tabsRef.value?.updateLineStyle(false)
}
效果展示
选择农历后:
农历切换到公里后:
测试闰月:
测试校验规则
三、完整代码
代码
<template>
<wd-popup
v-model="state.popupShow"
position="bottom"
custom-style="border-radius:32rpx;height: 300px;"
:close-on-click-modal="false"
@close="closeBirthdayPicker"
closable
@after-enter="handleOpened"
>
<wd-tabs v-model="state.birthdayIndex" animated swipeable ref="tabsRef" @change="onChangeTab">
<wd-tab v-for="(item, index) in state.birthdayArr" :key="index" :title="item">
<wd-picker-view
:columns="state.displayColumns"
v-model="state.birthday"
:column-change="onChangeColumn"
ref="birthdayPicker"
/>
</wd-tab>
</wd-tabs>
</wd-popup>
<div @click="openBirthdayPicker">
<wd-input
:prop="props.prop"
:rules="props.rules"
type="text"
label="生辰"
v-model="displayBirthday"
placeholder="请选择"
readonly
required
placeholder-style="color:#bfbfbf"
>
<template #suffix>
<!--箭头-->
<wd-icon name="arrow-right" color="rgba(0, 0, 0, 0.25)" size="18px" />
</template>
</wd-input>
</div>
</template>
<script lang="ts" setup>
import { LunarYear, LunarMonth, LunarHour, SolarTime, SolarMonth } from 'tyme4ts'
import { isArray } from 'wot-design-uni/components/common/util'
import { reactive, computed, watch, ref, defineProps, defineEmits, defineOptions } from 'vue'
import { FormItemRule } from 'wot-design-uni/components/wd-form/types'
defineOptions({
name: 'birthdayPicker',
})
onLoad(() => {
debugger
})
// 解决微信小程序Tabs表现异常
const tabsRef = ref<TabsInstance>()
function handleOpened() {
tabsRef.value?.updateLineStyle(false)
}
// 定义农历月份和日期的汉字表示
const chineseMonths = [
'一月',
'二月',
'三月',
'四月',
'五月',
'六月',
'七月',
'八月',
'九月',
'十月',
'十一月',
'十二月',
]
const chineseDays = [
'初一',
'初二',
'初三',
'初四',
'初五',
'初六',
'初七',
'初八',
'初九',
'初十',
'十一',
'十二',
'十三',
'十四',
'十五',
'十六',
'十七',
'十八',
'十九',
'二十',
'廿一',
'廿二',
'廿三',
'廿四',
'廿五',
'廿六',
'廿七',
'廿八',
'廿九',
'三十',
]
// 1.状态管理
const state = reactive({
displayColumns: [],
popupShow: false,
birthdayArr: ['农历', '公历'],
birthday: [],
birthdayIndex: 0,
pickerViewLoaded: false,
})
// 2.定义组件接收值
type bithdayPickerProps = {
modelValue: number[] // 生日值
disabled?: boolean // 是否禁用
prop: string // 表单域 model 字段名,在使用表单校验功能的情况下,该属性是必填的
rules: FormItemRule[] // 表单校验规则
}
const props = defineProps<bithdayPickerProps>()
const emit = defineEmits(['update:modelValue'])
// 3.计算Picker展示值
const findValueInCoulums = (value: number, columns: any[]) => {
let res = ''
columns.forEach((item) => {
if (item.value === value) res = item.label
})
return res
}
const displayBirthday = computed(() => {
const birthday = state.birthday
// 避免空数组调用join函数
if (isNullBirthdayArray(birthday, 4)) return null
// 公历2024年12月22日13时
return (
state.birthdayArr[state.birthdayIndex] +
birthday[0] +
'年' +
findValueInCoulums(birthday[1], state.displayColumns[1]) +
findValueInCoulums(birthday[2], state.displayColumns[2]) +
birthday[3] +
'时'
)
})
const isNullBirthdayArray = (birthday: number[], validLength: number = birthday.length) => {
return (
!birthday ||
(isArray(birthday) &&
(!birthday.length ||
birthday.length !== validLength ||
birthday.every((item) => item === null)))
)
}
// 4.初始化
onMounted(() => {
handleShowValueUpdate(props.modelValue)
})
// 5.监听父组件的值变化
watch(
() => props.modelValue,
(newValue) => {
handleShowValueUpdate(newValue)
},
)
// 6.值变更时更新显示内容
const handleShowValueUpdate = (value: number[]) => {
// 0.校验
if (isNullBirthdayArray(value, 5)) {
// 更新为初始值,状态值保持不变
updateColumns([1940, 1, 1, 1, 0])
return
}
// 1.获取选中项
state.birthday = [value[0], value[1], value[2], value[3]]
state.birthdayIndex = value[4]
// 2.更新列
updateColumns(value)
}
// 7.更新Columns:年份列、月份列、天数列、小时列
const yearColumns = Array.from({ length: new Date().getFullYear() - 1940 + 1 }, (_, i) => {
return { label: `${1940 + i}`, value: 1940 + i }
})
const hourColumns = Array.from({ length: 24 }, (_, i) => ({
label: `${i + 1}时`,
value: i + 1,
}))
const initDays = (len: number, type: 'lunar' | 'gregorian') =>
Array.from({ length: len }, (_, i) => {
return {
label: type === 'lunar' ? `${chineseDays[i]}` : `${i + 1}日`,
value: i + 1,
}
})
const updateColumns = (birthday: number[]) => {
let monthColumns = []
let dayColumns = []
const [_year, _month, _day, _hour, birthdayIndex] = birthday
// 1.农历列
if (birthdayIndex === 0) {
const lunarYear: LunarYear = LunarYear.fromYear(_year)
monthColumns = lunarYear.getMonths().map((month) => ({
label: month.isLeap()
? `闰${chineseMonths[month.getMonth() - 1]}`
: chineseMonths[month.getMonth() - 1],
value: month.getMonthWithLeap(),
}))
const lunarMonth: LunarMonth = LunarMonth.fromYm(_year, _month)
const dayCount: number = lunarMonth.getDayCount()
dayColumns = initDays(dayCount, 'lunar')
}
// 2.公历列
if (birthdayIndex === 1) {
monthColumns = Array.from({ length: 12 }, (_, i) => {
return { label: `${chineseMonths[i]}`, value: i + 1 }
})
const solarMonth: SolarMonth = SolarMonth.fromYm(_year, _month)
const dayCount: number = solarMonth.getDayCount()
dayColumns = initDays(dayCount, 'gregorian')
}
state.displayColumns = [yearColumns, monthColumns, dayColumns, hourColumns]
}
// 8.当用户滑动列后触发
const onChangeColumn = (pickerView, value, columnIndex, resolve) => {
// debugger
// 1.更新birthday值
const item = value[columnIndex]
state.birthday[columnIndex] = Number(item.value)
// 2.滑动列后重置后面的列
for (let i = columnIndex + 1; i < 4; i++) {
state.birthday[i] = 1
}
// 3.更新Columns列
updateColumns([...state.birthday, state.birthdayIndex])
// 4.更新pickerView
if (columnIndex === 0) {
pickerView.setColumnData(1, state.displayColumns[1])
pickerView.setColumnData(2, state.displayColumns[2])
pickerView.setColumnData(3, state.displayColumns[3])
} else if (columnIndex === 1) {
pickerView.setColumnData(2, state.displayColumns[2])
pickerView.setColumnData(3, state.displayColumns[3])
} else if (columnIndex === 2) {
pickerView.setColumnData(3, state.displayColumns[3])
}
// 5.更新pickerView组件
resolve()
}
// 9.当农历、公历切换时:
const onChangeTab = (index) => {
state.pickerViewLoaded = true
const [_year, _month, _day, _hour] = state.birthday
// 1.农历转公历
if (index.name === 1) {
console.log('农历转公历前', index.name, state.birthday)
const lunarHour = LunarHour.fromYmdHms(_year, _month, _day, _hour, 0, 0)
const solarTime: SolarTime = lunarHour.getSolarTime()
state.birthday = [
solarTime.getYear(),
solarTime.getMonth(),
solarTime.getDay(),
solarTime.getHour(),
]
console.log('农历转公历后', index.name, state.birthday)
}
// 2.公历转农历
if (index.name === 0) {
console.log('公历转农历前', index.name, state.birthday)
const solarTime = SolarTime.fromYmdHms(_year, _month, _day, _hour, 0, 0)
const lunarHour = solarTime.getLunarHour()
state.birthday = [
lunarHour.getYear(),
lunarHour.getMonth(),
lunarHour.getDay(),
lunarHour.getHour(),
]
console.log('公历转农历后', index.name, state.birthday)
}
// 3.更新Columns列,注意此时state.birthdayIndex还未更新
updateColumns([...state.birthday, index.name])
}
// 打开生日选择器
const openBirthdayPicker = () => {
if (props.disabled) return
state.popupShow = true
const value = props.modelValue
if (isNullBirthdayArray(value, 5)) {
state.birthday = [1940, 1, 1, 1]
state.birthdayIndex = 0
return
}
state.birthday = [value[0], value[1], value[2], value[3]]
state.birthdayIndex = value[4]
}
// 关闭生日选择器
const closeBirthdayPicker = () => {
emit('update:modelValue', [...state.birthday, state.birthdayIndex])
state.popupShow = false
}
</script>
<style lang="scss" scoped></style>
下一步建议
近期本人时间有限,暂不做改进,大佬们可以拿去做完善。
- 缺少 取消和确认 的操作。
- 组件不够通用,需要暴漏常用的函数和变量。
📌 [ 笔者 ] 文艺倾年
📃 [ 更新 ] 2024.12.22
❌ [ 勘误 ] /* 暂无 */
📜 [ 声明 ] 由于作者水平有限,本文有错误和不准确之处在所难免,
本人也很想知道这些错误,恳望读者批评指正!