# Vue + TypeScript Web应用实践

> 项目各类代码规范作用详见小白[项目规范最佳实践](https://github.com/fff455/tech-share/blob/master/Engineering/%E9%A1%B9%E7%9B%AE%E8%A7%84%E8%8C%83%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5.md)一文

## 项目创建

使用`@vue/cli`脚手架的`vue-ui`创建项目。

* 创建过程中需要注意的点:
  * 开启TypeScript，关闭`class-style component syntax`，开启该功能会引入`vue-property-decorator`依赖，在`vue-ts`项目中，通过使用`@Component`等装饰器来简化书写。习惯于使用装饰器等语法可选择使用。
  * 使用`dart-sass`作为CSS与处理器
  * 不使用脚手架提供的自动配置`eslint`，后续手工添加配置
  * 开启`PWA Support`

## VSCode插件添加

* Prettier、ESLint、stylelint、Vetur

## Prettier配置

* 配置`.prettierrc`以规范代码风格，配置内容如下。配置完成后，vscode开启配置，通过`Prettier`插件在保存文件时，自动完成代码格式化。

  ```
  {
    "tabWidth": 2, // 缩进空格为2，
    "useTabs": false, // 不使用Tab作为缩进
    "printWidth": 100, // 单行代码最多字符数，将vscode单屏可视部分作为最大长度即可
    "semi": true, // 使用分号
    "singleQuote": true, // 字符串单引号
    "arrowParens": "avoid", // 单入参箭头函数可不带括号
    "trailingComma": "all", // 对象属性后添加逗号
    "bracketSpacing": true, // 括号前后增加括号
    "jsxSingleQuote": true,
    "jsxBracketSameLine": false,
    "insertPragma": false,
    "ignorePath": ".prettierignore" // ignore文件对应路径
  }
  ```

## ESLint配置

* Vue部分正常配置即可，重点关注TypeScript部分的配置

  * 增加以下两个依赖

  ```
  $ yarn add -D @typescript-eslint/parser
  $ yarn add -D @typescript-eslint/eslint-plugin
  ```

  * 在`.eslintrc.js`中增加以下配置

    ```javascript
    module.export = {
      // ...
      parserOptions: {
        parser: '@typescript-eslint/parser', // TypeScript parser
        ecmaVersion: 8, // ES版本
        project: ['./tsconfig.json'], // tsconfig路径
      },
      plugins: ['@typescript-eslint'], // 启用typescript-eslint插件
      extends: [
        // ...
        'plugin:@typescript-eslint/recommended',
        '@vue/typescript/recommended',
      ],
      rules: {
        // ...
        '@typescript-eslint/no-explicit-any': 'error', // 显式any类型定义报错
        '@typescript-eslint/no-unused-expressions': ['error'], // 未使用变量报错
      },
    }
    ```
  * 由于使用`@vue/cli`构建项目时，已开启TypeScript，直接使用脚手架创建的`tsconfig.json`即可，但由于项目中同样存在js文件，所以需要增加js配置，来保证`typescript-eslint`也能够对js文件生效。

    ```
    {
      ...
      "include": [
        "*.js", // 增加js配置
        ".eslintrc.js"
      ],
    }
    ```
  * vscode安装`ESLint`插件后，在右下角开启ESLint检测，运行项目后，若有ESLint运行报错，根据报错内容解决即可。若为代码格式报错，保存后即可实现代码自动规范。保存自动规范需要通过配置`vscode`设置文件`setting.json`开启。之后`ESLint`正常开启检测。

    ```javascript
    {
      "editor.formatOnPaste": true,
      "editor.formatOnType": true,
      "eslint.codeAction.showDocumentation": {
          "enable": true
      },
      "editor.codeActionsOnSave": {
          "source.fixAll": true
      },
      "[javascript]": {
          "editor.defaultFormatter": "esbenp.prettier-vscode"
      },
      "[vue]": {
          "editor.defaultFormatter": "esbenp.prettier-vscode"
      }
    }
    ```

## stylelint配置

> 配置`stylelint`实现样式代码的规范化。

* 安装依赖
  * stylelint

    ```
    $ yarn -D stylelint stylelint-config-stylelint
    ```
  * scss插件

    ```
    $ yarn -D stylelint-scss
    ```
  * 样式规则排序

    ```
    $ yarn -D stylelint-order
    ```
* 增加`stylelint`配置

  ```javascript
  // .stylelintrc.js
  module.exports = {
    extends: 'stylelint-config-standard',
    plugins: [
      'stylelint-order',
      'stylelint-scss',
    ],
    rules: {
      'color-no-invalid-hex': true, // 禁止无效十六进制颜色
      'property-no-unknown': true, // 禁止unknown属性
      'string-no-newline': true, // 禁止字符串类属性换行
      'unit-no-unknown': true, // 禁止unknown样式单位
      'order/order': [
        'declarations',
        'custom-properties',
        'dollar-variables',
        'rules',
        'at-rules'
      ],
      'order/properties-order': [
        // 自定义样式规则顺序
      ]
    }
  }
  ```
* 上述配置中，`order/order`中的顺序样例

  ```css
  a {
    /* declaration */
    --width: 10px;
    /* custom-properties */
    $height: 20px;
    /* dollar-variables */
    display: none;
    /* rules */
    span {}
    /* at-rules */
    @media (min-width: 100px) {}
  }
  ```
* stylelint至此已经能够正确生效。

## Lint-staged配置

> 通过`lint-staged`在代码commit前对代码规范进行检测，防止非规范代码递交。

* 安装`husky`

  ```
  $ yarn add -D husky
  ```
* `husky`能够为`git`增加`git hook`，使我们可以在对应的钩子下增加我们需要的命令，`lint-staged`的功能就是在`pre-commit`这个钩子的阶段，增加对暂存区代码规范性的检测，防止不符合代码规范的代码进行递交。
* `pre-commit`配置与验证，`package.json`增加`pre-commit`的`git-hook`

  ```javascript
  "husky": {
    "hook": {
      "pre-commit": "echo \"git commit trigger husky pre-commit hook\" "
    }
  }
  ```
* `commit`本地更新后，`pre-commit`成功触发

  ![husky](/files/-MQeVspUwAGcoLGSpa8q)
* 安装`lint-staged`

  ```
  yarn add -D lint-staged
  ```
* `package.json`增加`lint-staged`的配置用于检测ts与vue文件，并在`pre-commit`中增加`lint-staged`执行命令

  ```javascript
  "husky": {
    "hook": {
      "pre-commit": "lint-staged "
    }
  },
  ```
* 新增`lint-staged`配置文件

  ```javascript
  // lint-staged.config.js
  module.exports = {
    'src/**/*.{ts,vue}': filenames => {
      return [
        'eslint --cache --quiet',
        'prettier --write',
        'stylelint src/**/*.{html,vue,css,sass,scss} --fix', // stylelint检测
      ];
    },
  };
  ```
* 对`lint-staged`功能进行验证。设置vscode，关闭on save时的代码自动格式化，编写一行不符合格式规范的代码，这里使用不带分号的代码进行验证。

  ```typescript
  // main.ts
  import Vue from 'vue' // 无分号
  ```
* `commit`代码触发`pre-commit`中的`lint-staged`命令，代码被`prettier`与`eslint`自动格式化，原无分号的代码已经自动增加分号

  ![lint-staged](/files/-MQeVspWVsIXi3O46uMH)

  ```typescript
  // main.ts
  import Vue from 'vue';
  ```

## lint-staged tsc

> 在lint-staged中增加TypeScript的检测


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xiaobaiha.gitbook.io/tech-share/vue/vue+typescript-xiang-mu-shi-jian.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
