鴻蒙OSUniApp導航欄組件開發:打造清新簡約的用戶界面#三方框架 #Uniapp

UniApp 開發實戰:打造符合鴻蒙設計風格的日歷活動安排組件

在移動應用開發中,日歷和活動安排是非常常見的需求。本文將詳細介紹如何使用 UniApp 框架開發一個優雅的日歷活動安排組件,并融入鴻蒙系統的設計理念,實現一個既美觀又實用的功能模塊。

設計理念

在開發這個組件之前,我們需要深入理解鴻蒙系統的設計哲學。鴻蒙系統強調"自然、流暢、統一"的設計原則,這些特點將貫穿我們的整個組件實現過程:

  1. 自然:日歷的切換和選擇要符合用戶的直覺
  2. 流暢:動畫過渡要平滑,操作響應要及時
  3. 統一:視覺元素要保持一致性,符合系統設計規范
  4. 高效:快速獲取和展示日程信息

組件實現

1. 日歷選擇器組件

首先實現一個基礎的日歷選擇器組件:

<!-- components/harmony-calendar/harmony-calendar.vue -->
<template><view class="harmony-calendar"><view class="calendar-header"><view class="month-switcher"><text class="iconfont icon-left" @click="changeMonth(-1)"></text><text class="current-month">{{ currentYear }}年{{ currentMonth + 1 }}月</text><text class="iconfont icon-right" @click="changeMonth(1)"></text></view><view class="weekday-header"><text v-for="day in weekDays" :key="day">{{ day }}</text></view></view><view class="calendar-body" :class="{ 'with-animation': enableAnimation }"><view class="days-grid"><view v-for="(day, index) in daysArray" :key="index"class="day-cell":class="[{ 'current-month': day.currentMonth },{ 'selected': isSelected(day.date) },{ 'has-events': hasEvents(day.date) }]"@click="selectDate(day)"><text class="day-number">{{ day.dayNumber }}</text><view v-if="hasEvents(day.date)" class="event-indicator"></view></view></view></view></view>
</template><script>
export default {name: 'HarmonyCalendar',props: {events: {type: Array,default: () => []},selectedDate: {type: Date,default: () => new Date()}},data() {return {currentDate: new Date(),currentMonth: new Date().getMonth(),currentYear: new Date().getFullYear(),weekDays: ['日', '一', '二', '三', '四', '五', '六'],enableAnimation: true,daysArray: []}},watch: {currentMonth: {handler() {this.generateCalendar()},immediate: true}},methods: {generateCalendar() {const firstDay = new Date(this.currentYear, this.currentMonth, 1)const lastDay = new Date(this.currentYear, this.currentMonth + 1, 0)const daysInMonth = lastDay.getDate()const startingDay = firstDay.getDay()let days = []// 上個月的日期const prevMonth = new Date(this.currentYear, this.currentMonth - 1, 1)const daysInPrevMonth = new Date(this.currentYear, this.currentMonth, 0).getDate()for (let i = startingDay - 1; i >= 0; i--) {days.push({date: new Date(prevMonth.getFullYear(), prevMonth.getMonth(), daysInPrevMonth - i),dayNumber: daysInPrevMonth - i,currentMonth: false})}// 當前月的日期for (let i = 1; i <= daysInMonth; i++) {days.push({date: new Date(this.currentYear, this.currentMonth, i),dayNumber: i,currentMonth: true})}// 下個月的日期const remainingDays = 42 - days.length // 保持6行固定高度for (let i = 1; i <= remainingDays; i++) {days.push({date: new Date(this.currentYear, this.currentMonth + 1, i),dayNumber: i,currentMonth: false})}this.daysArray = days},changeMonth(delta) {const newDate = new Date(this.currentYear, this.currentMonth + delta, 1)this.currentMonth = newDate.getMonth()this.currentYear = newDate.getFullYear()this.enableAnimation = truesetTimeout(() => {this.enableAnimation = false}, 300)},isSelected(date) {return date.toDateString() === this.selectedDate.toDateString()},hasEvents(date) {return this.events.some(event => new Date(event.date).toDateString() === date.toDateString())},selectDate(day) {this.$emit('date-selected', day.date)}}
}
</script><style lang="scss">
.harmony-calendar {background-color: #ffffff;border-radius: 24rpx;padding: 32rpx;box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);.calendar-header {margin-bottom: 32rpx;.month-switcher {display: flex;justify-content: space-between;align-items: center;margin-bottom: 24rpx;.current-month {font-size: 32rpx;font-weight: 500;color: #333333;}.iconfont {font-size: 40rpx;color: #666666;padding: 16rpx;&:active {opacity: 0.7;}}}.weekday-header {display: grid;grid-template-columns: repeat(7, 1fr);text-align: center;text {font-size: 28rpx;color: #999999;padding: 16rpx 0;}}}.calendar-body {.days-grid {display: grid;grid-template-columns: repeat(7, 1fr);gap: 8rpx;.day-cell {aspect-ratio: 1;display: flex;flex-direction: column;align-items: center;justify-content: center;position: relative;border-radius: 16rpx;transition: all 0.2s ease-in-out;&.current-month {background-color: #f8f8f8;.day-number {color: #333333;}}&.selected {background-color: #2979ff;.day-number {color: #ffffff;}.event-indicator {background-color: #ffffff;}}.day-number {font-size: 28rpx;color: #999999;}.event-indicator {width: 8rpx;height: 8rpx;border-radius: 4rpx;background-color: #2979ff;position: absolute;bottom: 12rpx;}&:active {transform: scale(0.95);}}}}&.with-animation {.days-grid {animation: fadeInScale 0.3s ease-out;}}
}@keyframes fadeInScale {from {opacity: 0.5;transform: scale(0.95);}to {opacity: 1;transform: scale(1);}
}
</style>

2. 活動列表組件

接下來實現活動列表組件,用于展示選中日期的活動:

<!-- components/schedule-list/schedule-list.vue -->
<template><view class="schedule-list"><view class="list-header"><text class="title">活動安排</text><text class="add-btn" @click="$emit('add')">添加</text></view><view class="list-content"><template v-if="filteredEvents.length"><view v-for="event in filteredEvents" :key="event.id"class="schedule-item":class="{ 'completed': event.completed }"@click="toggleEvent(event)"><view class="event-time">{{ formatTime(event.time) }}</view><view class="event-info"><text class="event-title">{{ event.title }}</text><text class="event-location" v-if="event.location">{{ event.location }}</text></view><text class="iconfont icon-check"></text></view></template><view v-else class="empty-tip"><image src="/static/empty.png" mode="aspectFit"></image><text>暫無活動安排</text></view></view></view>
</template><script>
export default {name: 'ScheduleList',props: {selectedDate: {type: Date,required: true},events: {type: Array,default: () => []}},computed: {filteredEvents() {return this.events.filter(event => new Date(event.date).toDateString() === this.selectedDate.toDateString()).sort((a, b) => new Date(`${a.date} ${a.time}`) - new Date(`${b.date} ${b.time}`))}},methods: {formatTime(time) {return time.slice(0, 5) // 只顯示小時和分鐘},toggleEvent(event) {this.$emit('toggle', event)}}
}
</script><style lang="scss">
.schedule-list {margin-top: 32rpx;.list-header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 24rpx;.title {font-size: 32rpx;font-weight: 500;color: #333333;}.add-btn {font-size: 28rpx;color: #2979ff;padding: 16rpx;&:active {opacity: 0.7;}}}.list-content {.schedule-item {display: flex;align-items: center;padding: 24rpx;background-color: #ffffff;border-radius: 16rpx;margin-bottom: 16rpx;box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);transition: all 0.2s ease-in-out;&.completed {opacity: 0.6;.event-info {text-decoration: line-through;}.icon-check {color: #52c41a;}}.event-time {font-size: 28rpx;color: #666666;margin-right: 24rpx;min-width: 100rpx;}.event-info {flex: 1;.event-title {font-size: 28rpx;color: #333333;margin-bottom: 8rpx;}.event-location {font-size: 24rpx;color: #999999;}}.icon-check {font-size: 40rpx;color: #dddddd;}&:active {transform: scale(0.98);}}.empty-tip {text-align: center;padding: 64rpx 0;image {width: 200rpx;height: 200rpx;margin-bottom: 16rpx;}text {font-size: 28rpx;color: #999999;}}}
}
</style>

3. 使用示例

下面展示如何在頁面中使用這兩個組件:

<!-- pages/schedule/schedule.vue -->
<template><view class="schedule-page"><harmony-calendar:events="events":selected-date="selectedDate"@date-selected="handleDateSelect"></harmony-calendar><schedule-list:events="events":selected-date="selectedDate"@toggle="toggleEventStatus"@add="showAddEventPopup"></schedule-list><!-- 添加活動彈窗 --><uni-popup ref="addEventPopup" type="bottom"><view class="add-event-form"><input v-model="newEvent.title" placeholder="活動標題" class="input-field" /><input v-model="newEvent.location" placeholder="活動地點" class="input-field" /><picker mode="time" :value="newEvent.time"@change="handleTimeChange"class="input-field"><view>{{ newEvent.time || '選擇時間' }}</view></picker><button @click="saveEvent" class="save-btn":disabled="!newEvent.title || !newEvent.time">保存</button></view></uni-popup></view>
</template><script>
import HarmonyCalendar from '@/components/harmony-calendar/harmony-calendar'
import ScheduleList from '@/components/schedule-list/schedule-list'export default {components: {HarmonyCalendar,ScheduleList},data() {return {selectedDate: new Date(),events: [],newEvent: {title: '',location: '',time: '',completed: false}}},methods: {handleDateSelect(date) {this.selectedDate = date},showAddEventPopup() {this.$refs.addEventPopup.open()},handleTimeChange(e) {this.newEvent.time = e.detail.value},saveEvent() {const event = {...this.newEvent,id: Date.now(),date: this.selectedDate}this.events.push(event)this.$refs.addEventPopup.close()// 重置表單this.newEvent = {title: '',location: '',time: '',completed: false}// 提示保存成功uni.showToast({title: '添加成功',icon: 'success'})},toggleEventStatus(event) {const index = this.events.findIndex(e => e.id === event.id)if (index > -1) {this.events[index].completed = !this.events[index].completed}}}
}
</script><style lang="scss">
.schedule-page {padding: 32rpx;min-height: 100vh;background-color: #f5f5f5;
}.add-event-form {background-color: #ffffff;padding: 32rpx;border-radius: 24rpx 24rpx 0 0;.input-field {width: 100%;height: 88rpx;border-bottom: 2rpx solid #f0f0f0;margin-bottom: 24rpx;padding: 0 24rpx;font-size: 28rpx;}.save-btn {margin-top: 32rpx;background-color: #2979ff;color: #ffffff;border-radius: 44rpx;height: 88rpx;line-height: 88rpx;font-size: 32rpx;&:active {opacity: 0.9;}&[disabled] {background-color: #cccccc;}}
}
</style>

性能優化

  1. 虛擬列表優化

當活動數量較多時,可以使用虛擬列表優化性能:

// 在 schedule-list 組件中添加
import VirtualList from '@/components/virtual-list'export default {components: {VirtualList}// ...其他配置
}
  1. 狀態管理

對于大型應用,建議使用 Vuex 管理日程數據:

// store/modules/schedule.js
export default {state: {events: []},mutations: {ADD_EVENT(state, event) {state.events.push(event)},TOGGLE_EVENT(state, eventId) {const event = state.events.find(e => e.id === eventId)if (event) {event.completed = !event.completed}}},actions: {async fetchEvents({ commit }) {// 從服務器獲取數據const events = await api.getEvents()commit('SET_EVENTS', events)}}
}
  1. 緩存優化

使用本地存儲緩存日程數據:

// utils/storage.js
export const saveEvents = (events) => {try {uni.setStorageSync('schedule_events', JSON.stringify(events))} catch (e) {console.error('保存失敗:', e)}
}export const getEvents = () => {try {const events = uni.getStorageSync('schedule_events')return events ? JSON.parse(events) : []} catch (e) {console.error('讀取失敗:', e)return []}
}

適配建議

  1. 暗黑模式支持
// 在組件樣式中添加
.harmony-calendar {&.dark {background-color: #1c1c1e;.calendar-header {.current-month {color: #ffffff;}}.day-cell {&.current-month {background-color: #2c2c2e;.day-number {color: #ffffff;}}}}
}
  1. 響應式布局

使用 flex 布局和 rpx 單位確保在不同設備上的適配:

.schedule-page {display: flex;flex-direction: column;min-height: 100vh;@media screen and (min-width: 768px) {flex-direction: row;.harmony-calendar {flex: 0 0 400rpx;}.schedule-list {flex: 1;margin-left: 32rpx;}}
}

總結

通過本文的講解,我們實現了一個功能完整的日歷活動安排組件。該組件不僅具有優雅的界面設計,還融入了鴻蒙系統的設計理念,同時考慮了性能優化和多端適配等實際開發中的重要因素。

在實際開發中,我們可以根據具體需求對組件進行擴展,例如:

  • 添加重復活動功能
  • 實現活動提醒
  • 支持多人協作
  • 添加數據同步功能

希望這篇文章能夠幫助你更好地理解如何在 UniApp 中開發高質量的組件,同時也能為你的實際項目開發提供有價值的參考。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/85069.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85069.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/85069.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

在 HTML 文件中添加圖片的常用方法

本文詳解HTML圖片插入方法&#xff1a;1&#xff09;通過<img>標簽實現&#xff0c;必須含src和alt屬性&#xff1b;2&#xff09;路徑支持絕對/相對引用&#xff1b;3&#xff09;建議設置width/height保持比例&#xff1b;4&#xff09;響應式方案用srcset適配不同設備…

LangChain-自定義Tool和Agent結合DeepSeek應用實例

除了調用LangChain內置工具外&#xff0c;也可以自定義工具 實例1&#xff1a; 自定義多個工具 from langchain.agents import initialize_agent, AgentType from langchain_community.agent_toolkits.load_tools import load_tools from langchain_core.tools import tool, …

代碼隨想錄算法訓練營第60期第五十天打卡

大家好&#xff0c;首先感慨一下&#xff0c;時間過的真是快&#xff0c;不知不覺我們的訓練營就已經到第五十天了&#xff0c;首先祝賀自己一直在堅持&#xff0c;今天是我們動態規劃章節的收官之戰&#xff0c;明天我們就會走進一個全新的算法章節單調棧&#xff0c;我們要為…

如何發布npm包?

如何發布npm包&#xff1f; 1. 注冊賬號[npm官網](https://www.npmjs.com/)2. 檢查 npm 源是否在官方 npm 倉庫&#xff0c;如果不在&#xff0c;進行切換3. 檢查4. 打包配置5. 發布6. 使用錯誤&#xff1a;版本更新命令 1. 注冊賬號npm官網 2. 檢查 npm 源是否在官方 npm 倉庫…

AI工具使用的最佳實踐,如何通過AI工具提高創作與工作效率

隨著科技的迅猛發展&#xff0c;人工智能&#xff08;AI&#xff09;已從遙不可及的未來構想&#xff0c;轉變為廣泛應用于各行業的實用工具。AI不僅在內容創作、設計、寫作等領域展現出巨大潛力&#xff0c;還通過自動化和智能化顯著提升了工作效率。本文將深入探討如何通過選…

漏洞Reconfigure the affected application to avoid use of weak cipher suites. 修復方案

修復方案&#xff1a;禁用弱加密套件&#xff08;Weak Cipher Suites&#xff09; 1. 確認當前使用的加密套件 在修復前&#xff0c;先檢查應用程序或服務器當前支持的加密套件&#xff1a; OpenSSL (適用于HTTPS/TLS服務)openssl ciphers -v ALL:COMPLEMENTOFALL | sortNgi…

AI對軟件工程的影響及未來發展路徑分析報告

目錄 第一部分&#xff1a;引言 研究背景與意義 報告框架與方法論 第二部分&#xff1a;AI對不同行業軟件工程的影響分析 數字化行業 制造業 零售業 工業領域 第三部分&#xff1a;大廠AI軟件工程實踐案例分析 微軟 谷歌 阿里巴巴 華為 第四部分&#xff1a;未來…

WSL里執行python深度學習的一些方法記錄

安裝anaconda3&#xff1a; 可以直接從 Download Now | Anaconda 中下載&#xff0c;然后拷貝到WSL環境的某個目錄&#xff0c;執行 bash xxxxxxx.sh 即可安裝。 啟動jupyter notebook&#xff1a; 先conda activate 當前環境&#xff0c;然后pip install jupyter 此時&am…

使用 SpyGlass Power Verify 解決方案中的規則

本節提供了關于使用 SpyGlass Power Verify 解決方案 的相關信息。內容組織如下: SpyGlass Power Verify 簡介運行 SpyGlass Power Verify 解決方案在 SpyGlass Power Verify 解決方案中評估結果SpyGlass Power Verify 解決方案中的參數SpyGlass Power Verify 報告1 SpyGlass …

spring4第3課-ioc控制反轉-詳解依賴注入的4種方式

1&#xff0c;屬性注入&#xff1b; 2&#xff0c;構造函數注入&#xff1b;(通過類型&#xff1b;通過索引&#xff1b;聯合使用) 3&#xff0c;工廠方法注入&#xff1b;(非靜態工廠&#xff0c;靜態工廠) 4&#xff0c;泛型依賴注入&#xff1b;(Spring4 整合 Hibernate4…

使用Rust和并發實現一個高性能的彩色分形圖案渲染

分形與 Mandelbrot Mandelbrot 集 (Mandelbrot Set) 是復數平面上一個點的集合,以數學家 Benot Mandelbrot 的名字命名。它是最著名的分形之一。一個復數 c 是否屬于 Mandelbrot 集,取決于一個簡單的迭代過程: z n + 1 = z n 2 + c z_{n+1}=z_{n}^2+c zn+1?=zn2?+c 如果…

微信小程序的軟件測試用例編寫指南及示例--性能測試用例

以下是針對微信小程序的性能測試用例補充,結合代碼邏輯和實際使用場景,從加載性能、渲染性能、資源占用、交互流暢度等維度設計測試點,并標注對應的優化方向: 一、加載性能測試用例 測試項測試工具/方法測試步驟預期結果優化方向冷啟動加載耗時微信開發者工具「性能」面板…

行為型:觀察者模式

目錄 1、核心思想 2、實現方式 2.1 模式結構 2.2 實現案例 3、優缺點分析 4、適用場景 5、注意事項 1、核心思想 目的&#xff1a;針對被觀察對象與觀察者對象之間一對多的依賴關系建立起一種行為自動觸發機制&#xff0c;當被觀察對象狀態發生變化時主動對外發起廣播&…

t009-線上代駕管理系統

項目演示地址 摘 要 使用舊方法對線上代駕管理系統的信息進行系統化管理已經不再讓人們信賴了&#xff0c;把現在的網絡信息技術運用在線上代駕管理系統的管理上面可以解決許多信息管理上面的難題&#xff0c;比如處理數據時間很長&#xff0c;數據存在錯誤不能及時糾正等問題…

LVS-NAT 負載均衡群集

目錄 簡介 一、LVS 與群集技術基礎 1.1 群集技術概述 1.2 負載均衡群集的分層結構 1.3 負載均衡工作模式 二、LVS 虛擬服務器核心組件與配置 2.1 LVS 內核模塊與管理工具 2.2 負載調度算法解析 2.3 ipvsadm 管理工具實戰 三、NFS 共享存儲服務配置 3.1 NFS 服務基礎…

LLaMaFactory - 支持的模型和模板 常用命令

一、 環境準備 激活LLaMaFactory環境&#xff0c;進入LLaMaFactory目錄 cd LLaMA-Factoryconda activate llamafactory 下載模型 #模型下載 from modelscope import snapshot_download model_dir snapshot_download(Qwen/Qwen2.5-0.5B-Instruct) 二、啟動一個 Qwen3-0.6B…

EDW2025|數據治理的神話破除——從誤區到現實

在當今數據驅動的世界中&#xff0c;數據治理已成為企業成功的關鍵因素。然而&#xff0c;許多組織在實施數據治理時&#xff0c;常常被一些常見的誤區所困擾。本文將逐一破除這些誤區&#xff0c;揭示數據治理的真實面貌。 誤區一&#xff1a;你需要一個大的預算&#xff01;…

AIGC與影視制作:技術革命、產業重構與未來圖景

文章目錄 一、AIGC技術全景&#xff1a;從算法突破到產業賦能1. **技術底座&#xff1a;多模態大模型的進化路徑**2. **核心算法&#xff1a;從生成對抗網絡到擴散模型的迭代** 二、AIGC在影視制作全流程中的深度應用1. **劇本創作&#xff1a;從“靈感枯竭”到“創意井噴”**2…

ReactJS 中的 JSX工作原理

文章目錄 前言? 1. JSX 是什么&#xff1f;&#x1f527; 2. 編譯后的樣子&#xff08;核心機制&#xff09;&#x1f9f1; 3. React.createElement 做了什么&#xff1f;&#x1f9e0; 4. JSX 與組件的關系&#x1f504; 5. JSX 到真實 DOM 的過程&#x1f4d8; 6. JSX 與 Fr…

Spring Advisor增強規則實現原理介紹

Spring Advisor增強規則實現原理介紹 一、什么是 Advisor&#xff1f;1. Advisor 的定義與本質接口定義&#xff1a; 2. Advisor 的核心作用統一封裝切點與通知構建攔截器鏈的基礎實現增強邏輯的靈活組合 二. Sprin當中的實現邏輯1 Advisor 接口定義2 PointcutAdvisor 接口定義…