长沙销售公司 网站,电商app制作平台,网站域名 评估作价,jsp网站建立前言#xff1a;哈喽#xff0c;大家好#xff0c;今天给大家分享一篇文章#xff01;并提供具体代码帮助大家深入理解#xff0c;彻底掌握#xff01;创作不易#xff0c;如果能帮助到大家或者给大家一些灵感和启发#xff0c;欢迎收藏关注哦 #x1f495; 目录 Deep… 前言哈喽大家好今天给大家分享一篇文章并提供具体代码帮助大家深入理解彻底掌握创作不易如果能帮助到大家或者给大家一些灵感和启发欢迎收藏关注哦 目录 DeepSeek 助力 Vue3 开发打造丝滑的页眉Header前言页面效果指令输入属性定义1. 文本内容相关2. 样式相关3. 导航相关4. 响应式相关 事件定义1. 导航点击事件2. logo 点击事件 其他1. 组件结构设计2. 响应式设计3. 动画效果4. 可访问性 think组件代码 代码测试测试代码正常跑通附其他基本代码编写路由 src\router\index.js编写展示入口 src\App.vue 页面效果相关文章 ️✍️️️️⚠️⬇️·正文开始⬇️·✅❓ 0️⃣1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣*️⃣#️⃣
DeepSeek 助力 Vue3 开发打造丝滑的页眉Header
前言
DeepSeek 的发展将对 AI 行业格局产生深远影响推动行业的创新和发展。其开源策略和技术优势将吸引更多的开发者和企业参与到 AI 技术的研发和应用中促进 AI 技术的普及和推广。越来越多的中小企业将能够利用 DeepSeek 的技术开发出具有创新性的 AI 应用推动 AI 技术在各个行业的落地生根。同时DeepSeek 的出现也将加剧 AI 行业的竞争促使其他企业加大研发投入不断提升技术水平从而推动整个行业的技术进步。在激烈的竞争环境下企业将不断探索新的技术和应用场景推动 AI 技术向更高水平发展。
页面效果 指令输入 已经创建好了一个基于Vue3的组合式API的项目(Composition API)并能正常运行起来请帮我用 Vue3的组合式API(Composition API) 生成一个 页眉Header 的功能组件所有代码都保存在components/Header 下的文件夹中。功能组件的script标签中只有setup属性使用普通 JavaScript 实现,不使用TypeScript。 功能要有如下属性 属性定义
1. 文本内容相关
title用于设置页眉的标题文本类型为字符串这样可以方便在不同页面显示不同的标题。subtitle可选属性用于显示副标题类型为字符串丰富页眉的信息展示。logoSrc用于指定页眉中显示的 logo 图片的源地址类型为字符串方便用户自定义品牌标识。
2. 样式相关
backgroundColor用于设置页眉的背景颜色类型为字符串可以接受十六进制颜色码、RGB 颜色值等方便进行视觉风格的定制。textColor用于设置页眉内文本的颜色类型为字符串同样可以接受多种颜色表示方式。height设置页眉的高度类型可以是字符串包含单位如 60px或数字默认单位为 px方便控制页眉的布局。
3. 导航相关
navItems用于传递导航菜单项的数据类型为数组数组中的每个元素可以是包含 label菜单项文本和 href链接地址等属性的对象方便生成导航菜单。isSticky布尔类型用于控制页眉是否固定在页面顶部方便实现粘性导航效果。
4. 响应式相关
breakpoint用于指定响应式布局的断点类型为数字或字符串如 768px当屏幕宽度小于该值时可能会改变页眉的显示方式如切换为汉堡菜单。
事件定义
1. 导航点击事件
nav-click当用户点击导航菜单项时触发事件参数可以传递被点击菜单项的数据方便在父组件中进行页面跳转或其他操作。
2. logo 点击事件
logo-click当用户点击页眉中的 logo 时触发可用于实现返回首页等功能。
其他
1. 组件结构设计
考虑将导航菜单拆分为独立的子组件提高代码的可维护性和复用性。可以将搜索框等常见的页眉元素也作为可配置的部分方便用户根据需求添加或移除。
2. 响应式设计
使用 CSS 媒体查询或 Vue 的响应式 API 实现不同屏幕尺寸下的自适应布局确保在各种设备上都有良好的显示效果。
3. 动画效果
为页眉的显示和隐藏添加过渡动画如淡入淡出、滑动等提升用户体验。当导航菜单项被点击时可以添加一些交互动画如变色、放大等。
4. 可访问性
确保页眉中的文本和图标都有适当的 alt 属性和 aria-label提高屏幕阅读器等辅助设备的可访问性。保证导航菜单可以通过键盘进行操作方便残障人士使用。
你有更好的建议也可以添加要注明。组件定义好后给出5个及以上的调用示例。 下面是现有目录 vueAndDeepseek/ ├── src/ # 源代码目录 │ ├── assets/ # 静态资源 │ │ ├── base.css │ │ ├── main.css │ │ └── logo.svg │ ├── components/ # 组件目录 │ │ ├── HelloWorld.vue │ │ ├── TheWelcome.vue │ │ ├── WelcomeItem.vue │ │ ├── Progress/ │ │ │ └── Progress.vue │ │ ├── Accordion/ │ │ ├── BackToTop/ │ │ ├── Card/ │ │ ├── InfiniteScroll/ │ │ ├── Notification/ │ │ ├── Timeline/ │ │ ├── Switch/ │ │ ├── Tabs/ │ │ ├── Sidebar/ │ │ ├── Breadcrumbs/ │ │ ├── MasonryLayout/ │ │ ├── Rating/ │ │ ├── ColorPicker/ │ │ ├── RightClickMenu/ │ │ ├── RangePicker/ │ │ ├── Navbar/ │ │ ├── FormValidation/ │ │ ├── CopyToClipboard/ │ │ ├── ClickAnimations/ │ │ ├── ThumbnailList/ │ │ ├── KeyboardShortcuts/ │ │ ├── CommentSystem/ │ │ ├── QRCode/ │ │ ├── RadioButton/ │ │ ├── Slider/ │ │ ├── ScrollAnimations/ │ │ ├── TextInput/ │ │ ├── Divider/ │ │ ├── Checkbox/ │ │ ├── TagInput/ │ │ ├── DropdownSelect/ │ │ ├── List/ │ │ ├── Header/ │ │ ├── DatePicker/ │ │ └── icons/ │ ├── router/ # 路由配置 │ │ └── index.js │ ├── stores/ # Pinia 状态管理 │ │ └── counter.js │ ├── views/ # 页面组件 │ │ ├── ProgressView.vue │ │ ├── TabsView.vue │ │ ├── SwitchView.vue │ │ ├── TimelineView.vue │ │ ├── NotificationView.vue │ │ ├── CardView.vue │ │ ├── InfiniteScrollView.vue │ │ ├── BackToTopView.vue │ │ ├── AccordionView.vue │ │ ├── SidebarView.vue │ │ ├── BreadcrumbsView.vue │ │ ├── MasonryLayoutView.vue │ │ ├── RatingView.vue │ │ ├── ColorPickerView.vue │ │ ├── RightClickMenuView.vue │ │ ├── RangePickerView.vue │ │ ├── NavbarView.vue │ │ ├── FormValidationView.vue │ │ ├── CopyToClipboardView.vue │ │ ├── ClickAnimationsView.vue │ │ ├── ThumbnailListView.vue │ │ ├── KeyboardShortcutsView.vue │ │ ├── CommentSystemView.vue │ │ ├── QRCodeView.vue │ │ ├── RadioButtonView.vue │ │ ├── SliderView.vue │ │ ├── ScrollAnimationsView.vue │ │ ├── TextInputView.vue │ │ ├── DividerView.vue │ │ ├── CheckboxView.vue │ │ ├── TagInputView.vue │ │ ├── DropdownSelectView.vue │ │ ├── ListView.vue │ │ ├── HeaderView.vue │ │ ├── DatePickerView.vue │ │ └── AboutView.vue │ ├── App.vue # 根组件 │ └── main.js # 应用入口 ├── public/ # 公共资源目录 ├── index.html # HTML 模板 ├── package.json # 项目配置 ├── vite.config.js # Vite 配置 └── node_modules/ # 依赖包目录
think
组件代码
我帮你创建一个结构清晰、功能完善的Header组件。根据你的需求我会做以下额外优化
增加移动端汉堡菜单功能添加导航菜单的键盘可访问性实现平滑的过渡动画增加默认样式和安全的props验证
以下是组件代码 components/Header/ ├── Header.vue └── HeaderNav.vue
components/Header/HeaderNav.vue
script setup
defineProps({items: {type: Array,default: () [],validator: value value.every(item item.label item.href)}
})const emit defineEmits([navClick])const handleClick (item, event) {emit(navClick, { item, event })
}
/scripttemplatenav rolenavigation aria-labelMain navigationul classnav-listli v-for(item, index) in items :keyindexclassnav-itema:hrefitem.hrefclassnav-linkclick.preventhandleClick(item, $event)keydown.enterhandleClick(item, $event):aria-labelGo to ${item.label}rolebuttontabindex0{{ item.label }}/a/li/ul/nav
/templatestyle scoped
.nav-list {list-style: none;padding: 0;margin: 0;display: flex;gap: 1.5rem;
}.nav-link {text-decoration: none;transition: color 0.3s ease;cursor: pointer;
}.nav-link:hover {opacity: 0.8;
}media (max-width: 768px) {.nav-list {flex-direction: column;gap: 1rem;}
}
/stylecomponents/Header/Header.vue
script setup
import { ref, computed, watch, onMounted, onBeforeUnmount } from vue
import HeaderNav from ./HeaderNav.vueconst props defineProps({title: {type: String,required: true},subtitle: String,logoSrc: String,backgroundColor: String,textColor: String,height: [String, Number],navItems: {type: Array,default: () []},isSticky: Boolean,breakpoint: {type: [String, Number],default: 768}
})const emit defineEmits([logoClick, navClick])const isMobile ref(false)
const isMenuOpen ref(false)const headerStyles computed(() ({backgroundColor: props.backgroundColor || transparent,color: props.textColor || inherit,height: typeof props.height number ? ${props.height}px : props.height,position: props.isSticky ? sticky : static
}))const normalizedBreakpoint computed(() {const bp props.breakpointreturn typeof bp string ? parseInt(bp) : bp
})const checkViewport () {const width window.innerWidthisMobile.value width normalizedBreakpoint.valueif (!isMobile.value) isMenuOpen.value false
}const handleLogoClick (event) {emit(logoClick, event)
}const handleNavClick (payload) {emit(navClick, payload)if (isMobile.value) isMenuOpen.value false
}onMounted(() {checkViewport()window.addEventListener(resize, checkViewport)
})onBeforeUnmount(() {window.removeEventListener(resize, checkViewport)
})watch(() props.breakpoint, checkViewport)
/scripttemplateheader classheader:styleheaderStyles:class{ sticky-header: isSticky }div classheader-contentdiv classbrand-sectionimgv-iflogoSrc:srclogoSrcaltSite LogoclasslogoclickhandleLogoClickkeydown.enterhandleLogoClicktabindex0rolebutton/div classtitle-sectionh1 classtitle{{ title }}/h1h2 v-ifsubtitle classsubtitle{{ subtitle }}/h2/div/divHeaderNavv-if!isMobile:itemsnavItemsnavClickhandleNavClickclassdesktop-nav/buttonv-ifisMobileclasshamburgerclickisMenuOpen !isMenuOpenaria-labelToggle navigation menudiv classhamburger-boxdiv classhamburger-inner :class{ active: isMenuOpen }/div/div/button/divTransition nameslide-downdiv v-ifisMobile isMenuOpenclassmobile-nav-containerHeaderNav:itemsnavItemsnavClickhandleNavClickclassmobile-nav//div/Transition/header
/templatestyle scoped
.header {top: 0;left: 0;right: 0;z-index: 100;transition: all 0.3s ease;box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}.sticky-header {position: sticky;
}.header-content {display: flex;justify-content: space-between;align-items: center;padding: 0 2rem;height: 100%;
}.brand-section {display: flex;align-items: center;gap: 1rem;
}.logo {height: 40px;cursor: pointer;transition: transform 0.3s ease;
}.logo:hover {transform: scale(1.05);
}.title-section {display: flex;flex-direction: column;
}.title {margin: 0;font-size: 1.5rem;
}.subtitle {margin: 0;font-size: 0.9rem;opacity: 0.8;
}.hamburger {background: none;border: none;padding: 0.5rem;cursor: pointer;
}.hamburger-box {width: 30px;height: 24px;position: relative;
}.hamburger-inner {position: absolute;width: 100%;height: 2px;background-color: currentColor;transition: all 0.3s ease;
}.hamburger-inner::before,
.hamburger-inner::after {content: ;position: absolute;width: 100%;height: 2px;background-color: currentColor;transition: all 0.3s ease;
}.hamburger-inner::before {top: -8px;
}.hamburger-inner::after {top: 8px;
}.hamburger-inner.active {background-color: transparent;
}.hamburger-inner.active::before {transform: translateY(8px) rotate(45deg);
}.hamburger-inner.active::after {transform: translateY(-8px) rotate(-45deg);
}.mobile-nav-container {background-color: inherit;padding: 1rem;
}.slide-down-enter-active,
.slide-down-leave-active {transition: all 0.3s ease;max-height: 500px;overflow: hidden;
}.slide-down-enter-from,
.slide-down-leave-to {max-height: 0;opacity: 0;
}media (max-width: 768px) {.header-content {padding: 0 1rem;}.title {font-size: 1.2rem;}
}
/style以下是5个使用示例
基础用法
Headertitle我的网站logoSrc/logo.png:navItems[{ label: 首页, href: / },{ label: 关于, href: /about }]
/带副标题和样式定制
Headertitle产品中心subtitle探索我们的解决方案backgroundColor#2c3e50textColor#ecf0f1:height80:isStickytrue
/响应式断点配置
Headertitle响应式示例:breakpoint1024:navItems[{ label: 服务, href: /services },{ label: 联系, href: /contact }]
/事件处理
Headertitle交互示例logo-clickhandleLogoClicknav-clickhandleNavClick:navItems[{ label: 博客, href: /blog },{ label: 文档, href: /docs }]
/完整配置示例
Headertitle完整示例subtitle欢迎访问我们的平台logoSrc/logo.pngbackgroundColorlinear-gradient(135deg, #667eea 0%, #764ba2 100%)textColor#ffffffheight100px:isStickytrue:breakpoint1024px:navItems[{ label: 产品, href: /products },{ label: 定价, href: /pricing },{ label: 支持, href: /support }]logo-clickgoToHomenav-clickhandleNavigation
/优化建议
性能优化添加防抖处理窗口resize事件可访问性为移动菜单添加点击外部关闭功能扩展性添加插槽系统来支持自定义内容区域SEO优化确保导航链接在服务器端渲染时可用安全增强对传入的logoSrc进行安全验证防止XSS攻击
如果需要实现这些额外功能可以进一步扩展组件逻辑。
代码测试 运行正常 测试代码正常跑通附其他基本代码
添加路由页面展示入口
编写路由 src\router\index.js import { createRouter, createWebHistory } from vue-router
import RightClickMenuView from ../views/RightClickMenuView.vue
import RangePickerView from ../views/RangePickerView.vueconst router createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: /,name: progress,component: () import(../views/ProgressView.vue),},{path: /tabs,name: tabs,// route level code-splitting// this generates a separate chunk (About.[hash].js) for this route// which is lazy-loaded when the route is visited.// 标签页Tabscomponent: () import(../views/TabsView.vue),},{path: /accordion,name: accordion,// 折叠面板Accordioncomponent: () import(../views/AccordionView.vue),},{path: /timeline,name: timeline,// 时间线Timelinecomponent: () import(../views/TimelineView.vue),},{path: /backToTop,name: backToTop,component: () import(../views/BackToTopView.vue)},{path: /notification,name: notification,component: () import(../views/NotificationView.vue)},{path: /card,name: card,component: () import(../views/CardView.vue)},{path: /infiniteScroll,name: infiniteScroll,component: () import(../views/InfiniteScrollView.vue)},{path: /switch,name: switch,component: () import(../views/SwitchView.vue)},{path: /sidebar,name: sidebar,component: () import(../views/SidebarView.vue)},{path: /breadcrumbs,name: breadcrumbs,component: () import(../views/BreadcrumbsView.vue)},{path: /masonryLayout,name: masonryLayout,component: () import(../views/MasonryLayoutView.vue)},{path: /rating,name: rating,component: () import(../views/RatingView.vue)},{path: /datePicker,name: datePicker,component: () import(../views/DatePickerView.vue)},{path: /colorPicker,name: colorPicker,component: () import(../views/ColorPickerView.vue)},{path: /rightClickMenu,name: rightClickMenu,component: RightClickMenuView},{path: /rangePicker,name: rangePicker,component: () import(../views/RangePickerView.vue)},{path: /navbar,name: navbar,component: () import(../views/NavbarView.vue)},{path: /formValidation,name: formValidation,component: () import(../views/FormValidationView.vue)},{path: /copyToClipboard,name: copyToClipboard,component: () import(../views/CopyToClipboardView.vue)},{path: /clickAnimations,name: clickAnimations,component: () import(../views/ClickAnimationsView.vue)},{path: /thumbnailList,name: thumbnailList,component: () import(../views/ThumbnailListView.vue)},{path: /keyboardShortcuts,name: keyboardShortcuts,component: () import(../views/KeyboardShortcutsView.vue)},{path: /commentSystem,name: commentSystem,component: () import(../views/CommentSystemView.vue)},{path: /qRCode,name: qRCode,component: () import(../views/QRCodeView.vue)},{path: /radioButton,name: radioButton,component: () import(../views/RadioButtonView.vue)},{path: /slider,name: slider,component: () import(../views/SliderView.vue)},{path: /scrollAnimations,name: scrollAnimations,component: () import(../views/ScrollAnimationsView.vue)},{path: /textInputView,name: textInputView,component: () import(../views/TextInputView.vue)},{path: /divider,name: divider,component: () import(../views/DividerView.vue)},{path: /checkbox,name: checkbox,component: () import(../views/CheckboxView.vue)},{path: /tagInput,name: tagInput,component: () import(../views/TagInputView.vue)},{path: /dropdownSelect,name: dropdownSelect,component: () import(../views/DropdownSelectView.vue)},{path: /list,name: list,component: () import(../views/ListView.vue)},{path: /header,name: header,component: () import(../views/HeaderView.vue)}],
})export default router
编写展示入口 src\App.vue script setup
import { RouterLink, RouterView } from vue-router
import HelloWorld from ./components/HelloWorld.vue
/scripttemplateheaderimg altVue logo classlogo src/assets/logo.svg width125 height125 /div classwrapperHelloWorld msgYou did it! /navRouterLink to/Progress/RouterLinkRouterLink to/tabsTabs/RouterLinkRouterLink to/accordionAccordion/RouterLinkRouterLink to/timelineTimeline/RouterLinkRouterLink to/backToTopBackToTop/RouterLinkRouterLink to/notificationNotification/RouterLinkRouterLink to/cardCard/RouterLinkRouterLink to/infiniteScrollInfiniteScroll/RouterLinkRouterLink to/switchSwitch/RouterLinkRouterLink to/sidebarSidebar/RouterLinkRouterLink to/breadcrumbsBreadcrumbs/RouterLinkRouterLink to/masonryLayoutMasonryLayout/RouterLinkRouterLink to/ratingRating/RouterLinkRouterLink to/datePickerDatePicker/RouterLinkRouterLink to/colorPickerColorPicker/RouterLinkRouterLink to/rightClickMenuRightClickMenu/RouterLinkRouterLink to/rangePickerRangePicker/RouterLinkRouterLink to/navbarNavbar/RouterLinkRouterLink to/formValidationFormValidation/RouterLinkRouterLink to/copyToClipboardCopyToClipboard/RouterLinkRouterLink to/clickAnimationsClickAnimations/RouterLinkRouterLink to/thumbnailListThumbnailList/RouterLinkRouterLink to/keyboardShortcutsKeyboardShortcuts/RouterLinkRouterLink to/commentSystemCommentSystem/RouterLinkRouterLink to/qRCodeQRCode/RouterLinkRouterLink to/radioButtonRadioButton/RouterLinkRouterLink to/sliderSlider/RouterLinkRouterLink to/scrollAnimationsScrollAnimations/RouterLinkRouterLink to/textInputViewTextInput/RouterLinkRouterLink to/dividerDivider/RouterLinkRouterLink to/checkboxCheckbox/RouterLinkRouterLink to/tagInputTagInput/RouterLinkRouterLink to/dropdownSelectDropdownSelect/RouterLinkRouterLink to/listList/RouterLinkRouterLink to/headerHeader/RouterLink/nav/div/headerRouterView /
/templatestyle scoped
header {line-height: 1.5;max-height: 100vh;
}.logo {display: block;margin: 0 auto 2rem;
}nav {width: 100%;font-size: 12px;text-align: center;margin-top: 2rem;
}nav a.router-link-exact-active {color: var(--color-text);
}nav a.router-link-exact-active:hover {background-color: transparent;
}nav a {display: inline-block;padding: 0 1rem;border-left: 1px solid var(--color-border);
}nav a:first-of-type {border: 0;
}media (min-width: 1024px) {header {display: flex;place-items: center;padding-right: calc(var(--section-gap) / 2);}.logo {margin: 0 2rem 0 0;}header .wrapper {display: flex;place-items: flex-start;flex-wrap: wrap;}nav {text-align: left;margin-left: -1rem;font-size: 1rem;padding: 1rem 0;margin-top: 1rem;}
}
/style
页面效果 相关文章 ———— 相 关 文 章 ———— DeepSeek 助力 Vue 开发打造丝滑的右键菜单RightClickMenuhttps://blog.csdn.net/qq_33650655/article/details/145706658 DeepSeek 助力 Vue 开发打造丝滑的范围选择器Range Pickerhttps://blog.csdn.net/qq_33650655/article/details/145713572 DeepSeek 助力 Vue 开发打造丝滑的导航栏Navbarhttps://blog.csdn.net/qq_33650655/article/details/145732421 DeepSeek 助力 Vue 开发打造丝滑的表单验证Form Validationhttps://blog.csdn.net/qq_33650655/article/details/145735582 DeepSeek 助力 Vue 开发打造丝滑的复制到剪贴板Copy to Clipboardhttps://blog.csdn.net/qq_33650655/article/details/145739569 DeepSeek 助力 Vue 开发打造丝滑的点击动画Click Animationshttps://blog.csdn.net/qq_33650655/article/details/145766184 DeepSeek 助力 Vue 开发打造丝滑的缩略图列表Thumbnail Listhttps://blog.csdn.net/qq_33650655/article/details/145776679 DeepSeek 助力 Vue 开发打造丝滑的 键盘快捷键Keyboard Shortcuts https://blog.csdn.net/qq_33650655/article/details/145780227 DeepSeek 助力 Vue 开发打造丝滑的评论系统Comment Systemhttps://blog.csdn.net/qq_33650655/article/details/145781104 DeepSeek 助力 Vue 开发打造丝滑的二维码生成QR Codehttps://blog.csdn.net/qq_33650655/article/details/145797928 DeepSeek 助力 Vue 开发打造丝滑的单选按钮Radio Buttonhttps://blog.csdn.net/qq_33650655/article/details/145810620 DeepSeek 助力 Vue 开发打造丝滑的滑块Sliderhttps://blog.csdn.net/qq_33650655/article/details/145817161 DeepSeek 助力 Vue 开发打造丝滑的滚动动画Scroll Animationshttps://blog.csdn.net/qq_33650655/article/details/145818571 DeepSeek 助力 Vue 开发打造丝滑的文本输入框Text Inputhttps://blog.csdn.net/qq_33650655/article/details/145837003 DeepSeek 助力 Vue 开发打造丝滑的分割线Dividerhttps://blog.csdn.net/qq_33650655/article/details/145849100 DeepSeek 助力 Vue 开发打造丝滑的 复选框Checkboxhttps://blog.csdn.net/qq_33650655/article/details/145855695 DeepSeek 助力 Vue3 开发打造丝滑的标签输入Tag Inputhttps://blog.csdn.net/qq_33650655/article/details/145858574 DeepSeek 助力 Vue3 开发打造丝滑的下拉选择框Dropdown Selecthttps://blog.csdn.net/qq_33650655/article/details/145861882 DeepSeek 助力 Vue3 开发打造丝滑的列表Listhttps://blog.csdn.net/qq_33650655/article/details/145866384 到此这篇文章就介绍到这了,更多精彩内容请关注本人以前的文章或继续浏览下面的文章创作不易如果能帮助到大家,希望大家多多支持宝码香车~若转载本文一定注明本文链接。 更多专栏订阅推荐 htmlcssjs 绚丽效果 vue ✈️ Electron ⭐️ js 字符串 ✍️ 时间对象Date()操作