技术栈
- vue2
- vuex
- vue-router
- webpack
- ES6/7
- axios
- less/sass
- vue-i18n
- 等...
src目录布局
├── src
│ ├── assets
│ │ ├── image // 公共图片
│ │ ├── style // 公共样式
│ ├── components // 存放公共组件
│ │ ├── button // 公共按钮组件
│ │ ├── footer // 公共底部组件
│ │ └── header // 公共头部组件
│ ├── config // 存放基本配置
│ ├── page // 存放业务组件,内部按模块进行区分,如下:
│ │ ├── shop // 商店组件
│ │ │ ├── children // 只在该模块用到的一些公共组件
│ │ │ │ ├── foodDetail.vue
│ │ │ │ └── shopDetail.vue
│ │ │ └── shop.vue // 该模块入口文件
│ ├── plugins // 存放引用的插件
│ ├── router
│ │ └── router.js // 路由配置
│ ├── service // api接口统一管理
│ ├── store // vuex的状态管理
│ │ ├── action // 配置actions
│ │ ├── getters // 配置getters
│ │ ├── index.js // 引用vuex,创建store
│ │ ├── mutationTypes // 定义常量muations名
│ │ └── mutations // 配置mutations
│ ├── App.vue // 页面入口文件
│ ├── main.js // 程序入口文件,加载各种公共组件
组件
1. 组件元素顺序保持一致,、
2. vue文件方法声明顺序
- components
- props
- data
- computed
- created
- mounted
- activited
- update
- beforeRouteUpdate
- metods
- filter
- watch
3. props规范
- 传值尽量简化,每一个属性单独使用一个 props,避免复杂的对象。使组件的API更加直观
- 验证组件的 props,保证组件的 props 能应对不同的情况,即使其他开发者并未按照你预想的方法使用时也不会出错。
- prop 的定义应该尽量详细,至少需要指定其类型。
data () {
return {
height:{
type: Number,
default: 0,
required: true,
validator: function (value) {
return value >= 0
}
},
}
},
- 使用 props 之前先检查该 prop 是否存在
4.公共组件必须保证是独立的, 可复用的,拒绝定制代码。要写组件使用说明。
//使用的时候,属性比较多的话分行写
5. 组件的每一个方法都要写注释
- 普通方法使用单行注释
// 说明该方法主要作用
- 复杂方法使用多行注释
/**
* @desc 说明该方法主要作用
* @param {Number} [age] - 参数说明
* @param {String} [name] - 参数说明
*/
6. 不要在 mounted、created 之类的方法写逻辑。
7. 尽量使用Vue的指令缩写 (用 : 表示 v-bind: 和用 @ 表示 v-on:)
8. css尽量使用类选择器,元素选择器比较慢
9. 使用Vuex 管理全局状态
10. 子组件内不要使用this.$parent直接访问父组件的上下文。访问组件之外的上下文违反了基于模块开发的第一原则。组件必须相互保持独立。
1、通过 props 将值传递给子组件
2、通过 props 传递回调函数给子组件来达到调用父组件方法的目的
3、通过在子组件触发事件来通知父组件
11. 尽量避免使用 this.$refs来访问其它组件的上下文。
12. 组件内不要使用复杂的行内表达式,可以使用 method 或是 computed 属性来替代其功能。复杂的行内表达式难以阅读,也不能复用。
13. v-if 和 v-for,v-for的优先级高于v-if。
-
两种常见的情况:
1、为了过滤一个列表中的项目 (比如v-for="item in dataList" v-if="item.isComplete"
)。
如果dataList是一个较为庞大的数组,请将 dataList 替换为一个计算属性 (比如 completeList),让其返回过滤后的列表。
2、隐藏整个列表,(比如v-for="item in dataList" v-if="shouldShowList"
)。
这种情形下,请将 v-if 移动至容器元素上。
router-路由
1. 使用懒加载
const Home = () => import('./Home.vue')
const router = new VueRouter({
routes: [
{
path: '/home',
name: 'home',
component: Home
}
]
})
2. 路由都添加 name 字段,路由跳转统一使用 name 进行跳转,方便管理
- 组件跳转
Home
- 方法跳转
this.$router.push({ name: 'home' })
vuex
1. 两种模式,一种按业务模块划分,一种按store的属性划分
-
按业务模块划分(业务逻辑比较复杂)
const modelA = {
state: {...},
mutations: {...},
actions: {...},
getters: {...},
}
const modelB = {
state: {...},
mutations: {...},
actions: {...},
getters: {...},
}
-
按store的属性划分(业务逻辑比较简单)
├── state.js
├── mutations.js
├── mutation-types.js
├── actions.js
├── getters.js
2. 组件内的使用
- 组件内使用state统一用mapState
computed:{
...mapState({
//使用this.countAlias
countAlias: 'count',
}),
...mapState([
//使用this.count
'count'
])
}
- 组件内使用getter统一用mapGetters
computed:{
...mapGetters({
//使用this.doneCount
doneCount: 'doneTodosCount'
}),
...mapGetters([
//使用this.doneTodosCount
doneTodosCount
])
}
- 组件内使用mutation统一用mapMutations
methods: {
...mapMutations([
// 将 `this.increment()` 映射为 `this.$store.commit('increment')`
'increment',
// 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
'incrementBy'
]),
...mapMutations({
// 将 `this.add()` 映射为 `this.$store.commit('increment')`
add: 'increment'
})
}
- components
- props
- data
- computed
- created
- mounted
- activited
- update
- beforeRouteUpdate
- metods
- filter
- watch
data () {
return {
height:{
type: Number,
default: 0,
required: true,
validator: function (value) {
return value >= 0
}
},
}
},
//使用的时候,属性比较多的话分行写
// 说明该方法主要作用
/**
* @desc 说明该方法主要作用
* @param {Number} [age] - 参数说明
* @param {String} [name] - 参数说明
*/
1、通过 props 将值传递给子组件
2、通过 props 传递回调函数给子组件来达到调用父组件方法的目的
3、通过在子组件触发事件来通知父组件
两种常见的情况:
1、为了过滤一个列表中的项目 (比如v-for="item in dataList" v-if="item.isComplete"
)。
如果dataList是一个较为庞大的数组,请将 dataList 替换为一个计算属性 (比如 completeList),让其返回过滤后的列表。
2、隐藏整个列表,(比如v-for="item in dataList" v-if="shouldShowList"
)。
这种情形下,请将 v-if 移动至容器元素上。
const Home = () => import('./Home.vue')
const router = new VueRouter({
routes: [
{
path: '/home',
name: 'home',
component: Home
}
]
})
Home
this.$router.push({ name: 'home' })
按业务模块划分(业务逻辑比较复杂)
const modelA = {
state: {...},
mutations: {...},
actions: {...},
getters: {...},
}
const modelB = {
state: {...},
mutations: {...},
actions: {...},
getters: {...},
}
按store的属性划分(业务逻辑比较简单)
├── state.js
├── mutations.js
├── mutation-types.js
├── actions.js
├── getters.js
computed:{
...mapState({
//使用this.countAlias
countAlias: 'count',
}),
...mapState([
//使用this.count
'count'
])
}
computed:{
...mapGetters({
//使用this.doneCount
doneCount: 'doneTodosCount'
}),
...mapGetters([
//使用this.doneTodosCount
doneTodosCount
])
}
methods: {
...mapMutations([
// 将 `this.increment()` 映射为 `this.$store.commit('increment')`
'increment',
// 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
'incrementBy'
]),
...mapMutations({
// 将 `this.add()` 映射为 `this.$store.commit('increment')`
add: 'increment'
})
}