内容 Content
- 模块化开发的基本原则
- 模块化开发的基本方法和流程
- 模块化开发实操:导航组件
. 一个组件只做一件事,保持组件功能的清晰和完整
. 设计组件时应考虑在应用的不同部分,甚至其他项目中都能重复使用
. 优化逻辑,模块化使用
. 根本目的
. 组件内部的逻辑和样式应保持私有,除非通过 props 或 emits 显式暴露出去
. 样式隔离:使用 CSS Modules 或 scoped 样式,防止样式冲突
. 组件不应直接依赖其他组件的内部逻辑
. 组件内的所有功能应在逻辑上紧密相关
. 合理设计 props :减少 props 的复杂度,尽量避免嵌套过深的对象或数组
. 灵活使用插槽:使用具名插槽、作用域插槽提升组件的扩展能力
. 解耦状态管理:对于复杂的组件,可以将状态抽离到 Pinia,避免组件间状态混乱
. 根据需要将 UI 逻辑、状态管理和业务逻辑分离
. 避免不必要的计算或重新渲染
. 在合适的地方使用记忆化 memoization 或计算属性 computed properties
. 在所有组件中使用一致的命名规范和设计模式
. 引入语法检测
. 组件组合式 API 封装:将通用逻辑抽离为自定义 Composition API,如 useFetch()、useDarkMode() 等,提升复用性
. 按需加载与异步组件:使用 defineAsyncComponent() 实现组件懒加载,提高首屏加载速度
. router 自带懒加载功能
. 明确组件的功能、输入输出,确定组件的使用场景
. 确定需要暴露的 props 和 emits
. 拆分组件结构,包括模板 template、逻辑 script 和样式style
. 使用 <slot> 实现内容扩展,提高灵活性
. 在 Vue 中,使用 defineProps() 接收父组件传入的数据
. 使用 defineEmits() 定义子组件向父组件通信的事件
. 编写组件内部逻辑和交互
. 完善组件的基本样式
. 全局注册
. 在父组件中引入并注册子组件
. 通过属性绑定传递数据
. 通过插槽传递内容
. 测试组件在不同场景下的表现
. 开发者工具或第三方工具
. 对组件进行性能优化,如避免不必要的渲染、合理拆分逻辑等
. 提供组件的使用说明、API 文档以及示例代码
温故而知新
学以致用
. 基于一个数组或对象来渲染一个列表
. 以数组为例;titles 是数据源;title 是迭代变量,表示数据项,可以是任何有效标识符;index 是数据项索引/位置序号
. 更多信息,请访问 列表渲染 v-for
import { ref } from 'vue'; const titles = ref([ { id:0, title: 'Foo' }, { id:1, title: 'Bar' }, { id:2, title: 'Baz' }, ])
<div v-for="(title, index) in titles" :key = "title.id"> // 其它内容 <div>{{ title.title }}</div> </div>
. 父组件 → 子组件传递参数/通信
. 更多信息,请访问 父传子 defineProps()
. 定义属性参数,暴露接口;这里暴露了一个字符串类型的属性 msg,默认为空;使用变量 props 接受
const props = defineProps({ msg: { type: String, default: '' } })
. 在结构中使用属性参数
<div>{{ msg }}</div>
. 引入子组件、定义属性参数
import { ref } from 'vue'; import Child from './components/Child.vue'; const msg = ref('hi, there.')
. 在结构中使用子组件并传递属性参数
<Child :msg = 'msg'></Child>
. 从结构上扩展组件功能;以默认插槽为例
. 更多信息,请访问 插槽 Slot
. 定义插槽
<div> // 组件其它内容 <slot></slot> </div>
. 引入、使用子组件
import Child from './components/Child.vue';
. 传递插槽,可以是任意内容;只能使用双标签形式
<Child> <div> // 插槽内容 </div> </Child>
. 基于矢量图形的字体文件;轻量、兼容性好、易于使用、可定制
. 更多信息,请访问 阿里字体图标 Iconfont
@import url(//at.alicdn.com/t/c/font_3859342_qe1ea0cgv5.css);
<span class="iconfont icon-home"></span>
. 最好显式的指定较高的层级 z-index,确保位于其它元素上层
. 更多信息,请访问 固定定位 Fixed、粘性定位 Sticky
.main-nav { position: fixed; bottom: 0; z-index: 99; }
.menu-nav { position: sticky; top: 0; z-index: 99; }
熟能生巧
没有规矩不成方圆
. 功能:导航
. 必选:使用文字提示
. 可选:其它提示,如图片、字体图标等
. 核心功能:使用 <RouterLink> 配合属性传参 defineProps() 实现
. 拓展功能:使用插槽 <slot> 实现;采用主流字体图标 Iconfont
. 字体图标:查找并引入字体图标在线链接到主样式文件 app.css
@import url(//at.alicdn.com/t/c/font_4235521_imop9zdge2.css);
Show Time
. 遵循 先静态后动态 的开发原则
. 在项目适当目录创建导航组件 NavItem.vue
. 静态设计
<RouterLink class="nav-item" to="/"> <span>Home</span> </RouterLink>
. 动态设计:使用自定义的属性参数替换静态数据部分
<RouterLink class="nav-item" :to="item.to"> <slot></slot> <span>{{ item.label }}</span> </RouterLink>
const props = defineProps({ item: { type: Object, default: {} } })
Show Time
. 引入导航组件、准备数据
. 这里采用静态数据源 items
import NavItem from '@/components/NavItem.vue' const items = [ { label: 'Home', icon: 'icon-home', to: '/' }, { label: 'Menu', icon: 'icon-thlist', to: '/menu' }, { label: 'Mall', icon: 'icon-shoppingcart', to: '/mall' }, { label: 'Memeber', icon: 'icon-statis', to: '/memeber' }, { label: 'Mine', icon: 'icon-account', to: '/mine' } ]
. 额外使用一个 <div> 便于布局
. 列表渲染导航数据
. 使用字体图标填充插槽;因为使用插槽,自定义组件必须使用双标签形式
<div class="nav"> <NavItem v-for="item in items" :key="item.label" :item> <span class="iconfont" :class="item.icon"></span> </NavItem> </div>
. 固定定位在视图底部
. 提升层级
. 弹性盒子水平分布导航项
.nav { position: fixed; left: 0; bottom: 0; width: 100%; height: var(--nav-h); z-index: 9; display: flex; justify-content: space-between; align-items: center; background-color: #f7f7f7; padding: 0 var(--p-m-g); }
Show Time
. 引入导航组件、准备数据
. 这里采用静态数据源 items;注意:to 应为全路径
import NavItem from '@/components/NavItem.vue' const items = [ { label: 'Goods', to: '/menu/goods' }, { label: 'Vip', to: '/menu/vip' }, { label: 'Rank', to: '/menu/rank' }, { label: 'Favorite', to: '/menu/favorite' }, ]
. 额外使用一个 <div>便于布局
. 列表渲染导航数据
. 没有使用插槽,自定义组件可以使用单标签形式
<div class="nav"> <NavItem v-for="item in items" :key="item.label" :item></NavItem> </div>
. 粘性定位在视图底部:视图滚动时,保持二级菜单始终显式在顶部
. 提升层级
. 弹性盒子水平分布导航项
.nav { position: sticky; Top: 0; display: flex; justify-content: space-between; align-items: center; padding: 0 var(--p-m-g); }
Show Time