# vue 单文件组件
## 基本原则
### 总体原则
1. 使用`setup`语法,`组合式 API`,而非`选项式 API`
2. 不要使用`mixins`,vue3中已不推荐使用,参考:[mixins](https://cn.vuejs.org/api/options-composition.html#mixins),[app.mixin()](https://cn.vuejs.org/api/application.html#app-mixin)
3. 不要在 `updated` 钩子中更改组件的状态,这可能会导致无限的更新循环!
4. 慎用`provide`和`inject`。
5. 慎用`watch`,能在`数据变化`源头进行操作的,就不要用`watch`。
6. 适时进行`组件拆分`,组件中代码长度不宜超过`300`行(概数,`少于`或者`略超`都可接受),宽度不宜超过`3/4 屏幕宽度`,代码应适时`空格`、`换行`、`空行`。
7. 每次提交代码之前,应移除`console.log`等无用代码。
### 组件拆分原则
1. 通常`v-for`遍历的`每一项`,应拆分为`独立组件`。除非`场景极其简单`,或者`确定后续不再更改`。
2. 通常`v-if`对应的`每一项`,应拆分为`独立组件`。除非`场景极其简单`,或者`确定后续不再更改`。
3. 通常`modal`组件中的内容,应拆分为`独立组件`。
4. 通常`drawer`组件中的内容,应拆分为`独立组件`。
5. 通常`popover`组件中的内容,应拆分为`独立组件`。
6. 通常`表单`应拆分为`独立组件`。
7. `过于复杂`的组件应设法拆分为`多个独立组件`
### 模板-template
1. `v-if`和`v-for`不要用在同一个节点上。
2. `v-for`必须加独立的唯一的`key`,如果API不返回,客户端应设法构造一个`唯一的可逆的key`
3. 任意节点的`key`都不能用`随机数`
4. 不要在模板里写`函数`,例如:``,这是糟糕的做法。
5. 不要在模板里写过多`js表达式`,请使用`计算属性`或者其他定义好的值。例如:绑定的样式对象直接在模板里书写,这是糟糕的做法。
6. 模板中的字符串使用`双引号`包裹,例如:`
`
7. 不要使用`v-else`,当在模板中存在条件判断时,应写完整的`v-if`,例如:`开
关
`。使用`v-else`不利于后续扩展
8. 请使用缩写指令,`@`代替`v-on`,`:`代替`v-bind`,`#`代替`v-slot`
9. 当节点上有`多个属性`时,应对每一个属性进行`换行`。
10. 在模板中使用`自定义组件`时,应写成`大写驼峰`(参考下方组件命名),而非`小写中横线`。
### 脚本-script
1. `js`中的字符串使用`单引号`包裹,例如:`const user_name = ref('zhangsan')`
2. 代码不宜写成一坨,要进行合理的`空行`。通常做`相似事情的代码`可连续书写,当代码进行到下一类事情时,需`空行`。例如声明多个变量,可连续书写,当将要声明一个函数时,需`空行`后再进行函数声明。
3. `关键词`与`操作符`之间要进行合理的`空格`
4. `注释`要清晰,必要时添加`文档`进行说明。请参考[jsdoc](https://jsdoc.nodejs.cn/)进行注释。
### 样式-style
1. 在样式中不要直接使用`元素选择器`。
2. 在样式中不要使用 `deep`
## 命名规范
为了`统一风格`,特对于项目中的`命名`进行一些规定。下方给出了一个项目的`src`目录中关键文件的`命名示例`。
```
src/
|- index.js
|- App.vue
|- assets/
|- images/
|- site-logo.png
|- man.svg
|- woman.svg
|- audio/
|- response-media.mp3
|- video/
|- movie.mp4
|- store/
|- index.js
|- use-counter.js
|- routes/
|- index.js
|- components/
|- account/
|- Login.vue
|- Register.vue
|- product/
|- ProductCreateForm.vue
|- ProductDetail.vue
|- shop-online/
|- ShopOnlineConfirmForm.vue
|- ShopOnlineStatus.vue
|- views/
|- Index.vue
|- About.vue
|- Login.vue
|- ProductDetail.vue
```
### 文件夹名称
`文件夹名称`一律`小写`,用`中横线`分隔。例如:`shop-online`
### 文件名称
除了`组件名`之外,其他类型的文件一律使用`小写英文字母`,使用`中横线`分隔。例如:`response-media.mp3`、`site-logo.png`
### 第三方组件名在模板中的使用
对于`第三方组件`,使用`小写`、`中横线`的方式进行书写。
```vue
Primary
Secondary
Dashed
Outline
Text
```
### 自定义组件名称
`组件名`使用`驼峰`形式命名,例如:`Index.vue`、`ProductDetail.vue`。
### 项目内自定义组件
对于`项目内`的`自定义组件`,使用`大写`、`驼峰`方式进行书写。
```vue
```
### props命名
`props`命名使用`小写`、`下划线`形式命名。例如下方的`props.user_age`、`props.user_name`。
```vue
```
### emit命名
`emit`命名使用`小写`、`驼峰`形式,例如:`priceChange`,`messageFinished`。
> 无需加`on`前缀,例如:`onPriceChange`,这是错误做法。
```vue
```
### 变量命名
同`props`命名,使用`小写`、`下划线`形式。
```js
const my_name = ref('张三');
const user_age = 18;
const theme_color = 'dark';
```
### 常量命名
`常量`使用`大写`字母加`下划线`的形式命名。
```js
const PROJECT_TITLE = '小数智能'; // 项目名称
const EXPIRE_VALUE = 3600; // 过期时间
```
### 函数命名
`函数`名称同`emit`命名
```js
function handleClick(){
}
/**
* 获取产品的ID
* @params {string} id - 产品ID
**/
function getProductInfo(id){
}
```
### 类命名
`类`使用`大写`、`驼峰`形式命名。
```js
class Human{
}
class Animals{
}
class ProductOrder{
}
```
## 关键顺序约定
### 单文件组件顺序
`单文件组件`中区块顺序按照`template`,`script`,`style`顺序进行书写。
```vue
组件模板
```
### 模板中元素属性的顺序
在模板中为元素绑定属性,需要遵循一定的顺序,大致顺序如下:
1. `v-`开头的指令,`v-if`、`v-show`、`v-for`
2. `key`、`class`、`style`、`id`、`title`等
3. 自定义属性,例如: `:age="18"`、`:price="300"`
4. 事件 `@click`、`@input`、`@change` 等
```vue
这是新闻的标题
```
### `script`标签内的顺序
在`单文件组件`中,各项顺序大致如下:
1. `import`
2. `defineProps`
3. `defineEmits`
4. `ref`、`reactive`、`let`、`const`、`var`等
5. `computed`
6. `watch`
7. `事件处理`方法
8. `生命周期钩子`:`onCreated`、`onMounted`、`onUpdated`、`onBeforeUnmount`
9. `defineExpose`
### css属性规则的顺序
样式的定义应遵循一定的顺序。
建议遵循以下顺序:
1. 布局定位属性:display / position / float / clear / visibility / overflow
2. 自身属性:width / height / margin / padding / border / background
3. 文本属性:color / font / text-decoration / text-align / vertical-align / white- space / break-word
4. 其他属性(CSS3):content / cursor / border-radius / box-shadow / text-shadow / background:linear-gradient …
> 参考:https://guide.aotu.io/docs/css/code.html#%E5%B1%9E%E6%80%A7%E4%B9%A6%E5%86%99%E9%A1%BA%E5%BA%8F
```css
.title{
display: block;
position: relative;
float: left;
width: 100px;
height: 100px;
margin: 0 10px;
padding: 20px 0;
font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif;
color: #333;
background: rgba(0,0,0,.5);
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-o-border-radius: 10px;
-ms-border-radius: 10px;
border-radius: 10px;
}
```