1. 工程目录规划
└─src
├─services # 服务相关
│ │
│ ├─ url.js # 请求地址
│ │
│ └─ map.js # 字段属性名映射(可能不需要)
| |
│ ├─ handler.js # 数据处理
│ │
│ └─ index.js
│
├─router # 路由
│ │
│ ├─ index.js # 路由入口
│ │
│ ├─ manager.js # 管理后台模块相关路由
│ │
│ └─ user.js # 用户模块相关路由
│
├─components # 公用组件
| ├─mixins # 混合
| │ │
| │ └─ CardMinix.vue # 卡片混合
│ │
│ └─ Common1.vue # 通用组件1
│ │
│ └─ Common2.vue # 通用组件2
│
├─views # 视图(业务组件)
| ├─manager # 后台管理视图
| │ │
| │ └─ Index.vue # 首页
| │ │
| │ └─ Export.vue # 数据查询/导出
| ├─user # 用户信息视图
| │ │
| │ └─ Profile.vue # 个人简介
| │ │
| │ └─ Detail.vue # 个人详情
├─store # 状态数据
| ├─manager # 后台管理state
| │ │
| │ └─ types.js
| │ │
| │ └─ action.js
| │ │
| │ └─ mutation.js
| │ │
| │ └─ state.js
| │ │
| │ └─ index.js
| ├─user # 用户信息state
| │ │
| │ └─ types.js
| │ │
| │ └─ action.js
| │ │
| │ └─ mutation.js
| │ │
| │ └─ state.js
| │ │
| │ └─ index.js
│
├─directives # 自定义指令
│
├─filters # 自定义过滤器
│
├─plugins # 自定义插件
│
├─config # 放置一些配置文件
│
├─utils # 放置一些工具函数
│
├─asserts # 静态资源
| │
| ├─less # 放置less
| │ │
| │ ├─ common.less # 通用less
| │ │
| │ └─ reset.less # 页面初始化less
| │
| ├─fonts # 放置iconfont字体
| ├─imgs # 放置图片
├─App.vue # 入口组件
├─main.js # 启动配置
其中,
- services目录中, 特别放置了
url.js
, 主要是为了方便管理所有的url请求地址, 有时后端提供的url不合规范, 后端重命名后, 对于前端来说, 修改起来是很方便的. ( 返回的数据不变的情况下, 如果返回的数据有变化, 就可能需要增加map.js
,handler.js
) -
components
和views
要严格区分, 与业务逻辑处理相关的都放在views
目录下, 公用组件都放置在components
目录下, 因为项目是不断迭代演进的过程, 有些组件可能需要多个工程复用, 有可能需要提取成npm包的形式, 此时, 严格区分业务形组件和通用组件就显得很重要了.
2. 文件引用路径别名设置
有时候项目文件过多,可能经常出现类似 "../../../static/data/xx.json" 这样的引用,写起来很麻烦而且经常容易出错(当然代码编译器能够提示就无所谓了),为了简化路径,我们可以在 build/webpack.base.conf.js 中去配置别名
这里是通过调用 resolve 方法来达到简化路径的目的,比如可以直接用@来取代src,也可以直接写 "api/xx.js",而不用一层一层的去找
3. 递归组件
在Vue中组件可以在模板内部递归调用自己,需要给组件设置name值,需要注意的是:必须限定条件,不能无限递归,否则会内存溢出(Error in nextTick: "RangeError: Maximum call stack size exceeded")。
场景: 在构建目录树时, 如果用一个组件来完成, 可能会涉及到复杂的数据处理和计算, 然后再渲染成一个目录树结构.
在此场景中, 可以写一个递归函数, 根据数据生成一个目录树节点, 然后渲染出来.
当然, 也可以考虑下使用递归组件来完成这样的工作.如:
// 父组件
官方文档里面写的递归组件强调了使用name属性,
// Items.vue
{{model.data.menuName}}
4. 路由懒加载
// Vue路由文档的写法:
const app = () => import('./app.vue') // 引入组件
const router = new VueRouter({
routes: [
{ path: '/app', component: app }
]
})
// 也要以这么写
const router = new VueRouter({
routes: [
{ path: '/app', component: () => import('./app.vue')}
]
})
5. 404页面
如果输入的路由不存在应该要跳转到404页面(自定义404页面)
export default new Router({
routes: [
{
path: '/', // 项目启动页
redirect:'/login' // 重定向到下方声明的路由
},
{
path: '*', // 404 页面
component: () => import('./notFind')
},
]
})
6. 路由拦截
场景描述:
当用户使用浏览器后退时, 提示用户保存未保存的表单。
//在路由组件中:
mounted(){
},
beforeRouteLeave (to, from, next) {
if(userInput){
//出现弹窗提醒保存表单,或者自动后台为其保存
}else{
next(true);//用户离开
}
请参考vue文档全局钩子和组件钩子
7. 深度watch与watch立即触发回调
watch很多人都在用,watch中的有两个选项deep、immediate
- deep, 在选项中指定deep: true, 可以监听对象中属性的变化
- immediate, 在选项中指定immediate:true, 将立即以表达式的当前值触发回调, 也就是默认触发一次.
watch: {
obj: {
handler(val, oldVal) {
console.log('属性发生变化触发这个回调',val, oldVal);
},
deep: true // 监听这个对象中的每一个属性变化
},
step: { // 属性
//watch
handler(val, oldVal) {
console.log("默认触发一次", val, oldVal);
},
immediate: true // 默认触发一次
},
},
8. 动态组件
9. 异步组件
通过使用异步组件工厂函数加载异步组件:
const AsyncComponent = () => ({
// 需要加载的组件 (应该是一个 `Promise` 对象), 也可以使用window.System.import(url)
component: import('./MyComponent.vue'),
// 异步组件加载时使用的组件
loading: LoadingComponent,
// 加载失败时使用的组件
error: ErrorComponent,
// 展示加载时组件的延时时间。默认值是 200 (毫秒)
delay: 200,
// 如果提供了超时时间且组件加载也超时了,
// 则使用加载失败时使用的组件。默认值是:`Infinity`
timeout: 3000
})
10. 组件动态传参
- v-bind
- $attr
- $listener
11. 组件通信
- provide
- inject
12, 嵌套组件生命周期钩子函数执行顺序
13. 嵌套路由的路由守卫函数执行顺序
更多好文:
- 页面性能优化常用办法汇总
- 五道ES6 Promise题, 助你快速理解Promise
- 从输入网址到页面呈现
- 经典的24个JavaScript面试题和答案!