ZONE_98F

ZONE_98F 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

ZONE_98F 赞了回答 · 8月26日

解决使用?. 好像是vscode一直报红,应该配置什么?

你能写出?.就表示你知道这个是可选链式调用
查字典可得以下单词
可选: optional
链式: chain
语法:syntax

clipboard.png
查谷歌可知大家都叫chaining而不是chain ,此时更换关键字为vscode optional chainning syntax后再搜

clipboard.png

很明显第一条就是

里面内容截图一览

clipboard.png
]

关注 3 回答 2

ZONE_98F 赞了文章 · 7月28日

从零构建前端 ESLint 工作流(2020手把手版)

从零构建前端 ESLint 工作流

  • eslint prettier stylelint husky lint-staged typescript eslint-config-alloy 为构建项目代码质量保驾护航。
  • 传承 ESLint 推崇的插件化、配置化的理念,满足个性化需求(即让专业的工具做擅长的事)因此,各位可以选择自己需要的功能进行集成。
  • 文章只发表于思否(不喜欢到处copy)各位有缘的老铁,点赞收藏支持一波哈(看到点赞收藏关注,有一种小鹿乱撞的美好)

选择性阅读

什么是代码检查

  • 代码检查主要是用来发现代码错误、统一代码风格。
  • 在 JavaScript 项目中,我们一般使用 ESLint 来进行代码检查,它通过插件化的特性极大的丰富了适用范围,搭配 typescript-eslint 之后,甚至可以用来检查 TypeScript 代码。

配置 ESLint

小试牛刀

1、新建一个文件夹,打开命令行,npm init -y创建package.json
2、安装依赖npm install --save-dev eslint babel-eslint eslint-config-alloy
3、在项目根目录下创建一个.eslintrc.js.eslintrc.json的配置文件:

// .eslintrc.js
module.exports = {
    extends: [
        'alloy',
    ],
};

4、在项目根目录下创建一个index.js,复制下面内容:

var myName = 'Tom';
console.log(`My name is ${myNane}`);

5、在命令行输入npx eslint index.js

// eslint 报错信息:
✖ 2 problems (2 errors, 0 warnings)
error  Unexpected var, use let or const instead  no-var
error  'myNane' is not defined                   no-undef

6、使用npx eslint index.js --fix自动修复某些规则

// 这时 var 变成了 let
// 还剩下一个无法自动修复的错误 
✖ 1 problem (1 error, 0 warnings)
error  'myNane' is not defined  no-undef

配合 TypeScript

1、由于 ESLint 默认使用 Espree 进行语法解析,无法识别 TypeScript 的一些语法,故我们需要安装 @typescript-eslint/parser,替代掉默认的解析器,别忘了同时安装 typescript:

npm install --save-dev typescript @typescript-eslint/parser

2、接下来需要安装对应的插件 @typescript-eslint/eslint-plugin 它作为 eslint 默认规则的补充,提供了一些额外的适用于 ts 语法的规则。

npm install --save-dev @typescript-eslint/eslint-plugin

3、修改配置文件

module.exports = {
    extends: [
        'alloy',
    ],
    parser: '@typescript-eslint/parser',
    plugins: ['@typescript-eslint'],
    rules: {
        // 禁止使用 var
        'no-var': "error",
        // 优先使用 interface 而不是 type
        '@typescript-eslint/consistent-type-definitions': [
            "error",
            "interface"
        ]
    }
}
  • 以上配置中,我们自定义了两个规则,其中 no-var是 ESLint 原生的规则(我们刚刚已经用到了这个规则,它被包含在alloy中,此处会覆盖),@typescript-eslint/consistent-type-definitions 是 @typescript-eslint/eslint-plugin 新增的规则
  • 规则的取值一般是一个数组(上例中的 @typescript-eslint/consistent-type-definitions),其中第一项是 off、warn 或 error 中的一个,表示关闭、警告和报错。后面的项都是该规则的其他配置。
  • 如果没有其他配置的话,则可以将规则的取值简写为数组中的第一项(上例中的 no-var)。
关闭、警告和报错的含义如下:
  • 关闭:禁用此规则
  • 警告:代码检查时输出错误信息,但是不会影响到 exit code
  • 报错:发现错误时,不仅会输出错误信息,而且 exit code 将被设为 1(一般 exit code 不为 0 则表示执行出现错误)

4、新建index.ts文件:

var myName = 'Tom';
console.log(`My name is ${myNane}`);
console.log(`My name is ${myName.toStrng()}`);
type Foo = {};

5、在命令行输入npx eslint index.ts,如下可以看到报错信息以及可修复项

  1:1   error  Unexpected var, use let or const instead  no-var
  2:27  error  'myNane' is not defined                   no-undef
  4:6   error  Use an `interface` instead of a `type`    @typescript-eslint/consistent-type-definitions

✖ 3 problems (3 errors, 0 warnings)
  2 errors and 0 warnings potentially fixable with the `--fix` option.

脚本命令检查整个项目

1、根目录新建一个src文件夹,将我们的index.jsindex.ts放进去
2、在package.json中的scripts新增:

{
    "scripts": {
        // 因为eslint不是全局安装的,所以要使用npx
        "lint": "npx eslint src --ext .js,.ts,tsx"
        // eslint 默认不会检查 .ts 后缀的文件,所以需要加上参数 --ext .ts
    }
}

3、然后npm run lint就可以看到src下所有指定后缀文件的报错信息

推荐使用 AlloyTeam 的配置

  • 上面手把手完成了ESLint的配置过程
  • 有一定经验的推荐直接使用AlloyTeam实现可自定义拓展的ESLint规则
  • AlloyTeam/eslint-config-alloy已经帮我们集成了各种技术栈

1、安装技术栈相关依赖

// Eslint
npm install --save-dev eslint babel-eslint eslint-config-alloy
// React
npm install --save-dev eslint babel-eslint eslint-plugin-react eslint-config-alloy
// Vue
npm install --save-dev eslint babel-eslint vue-eslint-parser eslint-plugin-vue eslint-config-alloy
// TypeScript
npm install --save-dev eslint typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-alloy
// TypeScript React
npm install --save-dev eslint typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react eslint-config-alloy

2、配置.eslintrc.js文件

/* .eslintrc.js */
module.exports = {
    extends: [
        'alloy', // 都需要
        'alloy/vue', //vue项目需要
        'alloy/react', //react项目需要
        'alloy/typescript', //ts项目需要
    ],
    env: {
        // 你的环境变量(包含多个预定义的全局变量)
        //
        // browser: true,
        // node: true,
        // mocha: true,
        // jest: true,
        // jquery: true
    },
    globals: {
        // 你的全局变量(设置为 false 表示它不允许被重新赋值)
        //
        // myGlobal: false
    },
    rules: {
        // 自定义你的规则
    }
};

3、接下来就可以直接用eslint命令检查文件了
4、这样就引入了alloy团队的lint规则了,然后可以用rules覆盖你不爽的规则,直接采用开源规则是为了避免重复造轮子,你也可以选择别的团队,或者自己定义一套

VSCode 集成 ESLint 检查

在编辑器中集成 ESLint 检查,可以在开发过程中就发现错误,甚至可以在保存时自动修复错误,极大的增加了开发效率

1、先安装 ESLint 插件,打开 VSCode 点击「扩展」按钮,搜索 ESLint,然后安装即可
2、在「文件 => 首选项 => 设置 => 工作区」中(也可以在项目根目录下创建一个配置文件 .vscode/settings.json),添加以下配置:

{
    // VSCode 中的 ESLint 插件默认是不会检查 `.vue`、`.ts` 或 `.tsx` 后缀的
    "eslint.validate": [
        "javascript",
        "javascriptreact",
        "vue",
        "typescript",
        "typescriptreact"
    ],
    // 开启保存时自动修复
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    },
    // 指定VSCode用于IntelliSense(智能感知)的ts版本,将内置版本更换为工作区版本
    "typescript.tsdk": "node_modules/typescript/lib"
}

结合 Prettier 使用

Prettier 是一个代码格式化工具,相比于 ESLint 中的代码格式规则,它提供了更少的选项,但是却更加专业。
AlloyTeam 推荐用 Prettier 管理格式化相关的规则,用 ESLint 来检查它更擅长的逻辑错误。

配置 Prettier

1、安装 Prettier

npm install --save-dev prettier

2、配置 .prettierrc.js 仅供参考:

// .prettierrc.js
module.exports = {
    // 一行最多 100 字符
    printWidth: 100,
    // 使用 4 个空格缩进
    tabWidth: 4,
    // 不使用缩进符,而使用空格
    useTabs: false,
    // 行尾需要有分号
    semi: true,
    // 使用单引号
    singleQuote: true,
    // 对象的 key 仅在必要时用引号
    quoteProps: 'as-needed',
    // jsx 不使用单引号,而使用双引号
    jsxSingleQuote: false,
    // 末尾不需要逗号
    trailingComma: 'none',
    // 大括号内的首尾需要空格
    bracketSpacing: true,
    // jsx 标签的反尖括号需要换行
    jsxBracketSameLine: false,
    // 箭头函数,只有一个参数的时候,也需要括号
    arrowParens: 'always',
    // 每个文件格式化的范围是文件的全部内容
    rangeStart: 0,
    rangeEnd: Infinity,
    // 不需要写文件开头的 @prettier
    requirePragma: false,
    // 不需要自动在文件开头插入 @prettier
    insertPragma: false,
    // 使用默认的折行标准
    proseWrap: 'preserve',
    // 根据显示样式决定 html 要不要折行
    htmlWhitespaceSensitivity: 'css',
    // 换行符使用 lf
    endOfLine: 'lf'
};

VSCode 集成 Prettier

1、在.vscode/settings.json中添加配置:

{
    // 保存时自动格式化所有支持文件 javascript/javascriptreact/typescript/typescriptreact/json/graphql
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "esbenp.prettier-vscode",
}

2、这时我们保存文件的时候,已经可以自动格式化了
3、也可以指定格式化文件类型:

{
    // Set the default
    "editor.formatOnSave": false,
    // Enable per-language
    "[javascript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode",
        "editor.formatOnSave": true
    }
}

继续集成 Stylelint

顾名思义,Stylelint帮我们解决类css文件样式问题

Stylelint 规则分为三个类别

  • Possible errors: 可以使用stylelint-config-recommended启用这些规则
  • Stylistic issues: stylelint-config-standard拓展了Possible errors,并启用此类的规则
  • Limit language features: 其他规则,如果有需要,可以在rules里面配置
  • 详尽的配置规则

Stylelint 配置

1、安装依赖

npm install --save-dev stylelint stylelint-config-standard stylelint-order

2、在项目根目录中创建一个.stylelintrc.js配置文件:

module.exports = {
    extends: [
        'stylelint-config-standard',
    ],
    plugins: ['stylelint-order'],
    rules: {
        // ...
    }
};
  • stylelint-config-standardstylelint的推荐配置
  • stylelint-order是 css 属性排序插件

3、npx stylelint "**/*.css" 尝试检查 css 文件

支持 SCSS

1、安装依赖

npm install --save-dev stylelint-config-sass-guidelines stylelint-scss

2、调整.stylelintrc.js配置文件:

module.exports = {
    extends: [
        'stylelint-config-standard',
        'stylelint-config-sass-guidelines',
    ],
    plugins: ['stylelint-order', 'stylelint-scss'],
    rules: {
        // ...
    }
};

3、更多配置及插件

VSCode 集成 Stylelint

1、在.vscode/settings.json中添加配置:

{
    "editor.codeActionsOnSave": {
         // 开启保存自动修复所有stylelint可修复的选项
        "source.fixAll.stylelint": true
    },
}

2、这时我们保存文件的时候,Stylelint已经可以自动修复,但是我们上面让Prettier负责了所有文件的格式化,因此可能会导致冲突,倒腾了好久VSCode配置项,效果并不好,比如去除了 css 等文件的格式化,到.vue内联<style>依然有问题:

{
    // 去除其他插件
    "css.validate": false,
    "less.validate": false,
    "scss.validate": false,
    // 编辑器格式化全部交给 Prettiern 配置
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    // 针对某种语言,配置替代编辑器设置,取消自动保存格式化
    "[css]": {
        "editor.formatOnSave": false
    },
    "[less]": {
        "editor.formatOnSave": false
    },
    "[scss]": {
        "editor.formatOnSave": false
    },
}

3、如上还是会有问题,换个思路,让Stylelint禁用所有与Prettiern有关的规则,很符合我们整篇文章「各司其职」的思想
4、安装依赖npm install --save-dev stylelint-config-prettier
5、调整.stylelintrc.js配置文件:

module.exports = {
    extends: [
        'stylelint-config-standard',
        'stylelint-config-sass-guidelines',
        'stylelint-config-prettier'
    ],
    plugins: ['stylelint-order', 'stylelint-scss'],
    rules: {
        // ...
    }
};

6、至此,我们让Prettiern负责格式化,让Stylelint检查样式,让ESLint检查语法逻辑,完成了整个前端 Lint 工作流

Git 代码预检

  • 上面我们配置了ESLint、Prettier、Stylelint集成了VSCode插件,实现了错误提示和保存自动修复
  • 然而自动修复的只是小部分,如果团队成员不按规范,依然可以将不规范的代码推送至远程代码库
  • 我们通过Git 代码预检,一定程度防止不规范的代码被提交

实现过程

  1. 待提交的代码
  2. git add 添加到暂存区
  3. 执行 git commit(这时进行代码预检)
  4. husky注册在git pre-commit的钩子调起 lint-staged
  5. lint-staged 取得所有被提交的文件依次执行写好的任务
  6. 如果有错误(没通过ESlint检查)则停止任务,等待下次commit,同时打印错误信息
  7. 成功提交后,git push推送到远程库

什么是 git hook

  • git hook就是.git文件夹的hooks下的一些钩子函数,特定时机他们将被调用
  • 查看所有 git 钩子函数:
cd .git/hooks
ls -l
// 打印如下:
total 96
-rwxr-xr-x  1 zzc  staff   478 10 21  2019 applypatch-msg.sample
-rwxr-xr-x  1 zzc  staff   896 10 21  2019 commit-msg.sample
-rwxr-xr-x  1 zzc  staff  3327 10 21  2019 fsmonitor-watchman.sample
-rwxr-xr-x  1 zzc  staff   189 10 21  2019 post-update.sample
-rwxr-xr-x  1 zzc  staff   424 10 21  2019 pre-applypatch.sample
-rwxr-xr-x  1 zzc  staff  1638 10 21  2019 pre-commit.sample
-rwxr-xr-x  1 zzc  staff  1348 10 21  2019 pre-push.sample
-rwxr-xr-x  1 zzc  staff  4898 10 21  2019 pre-rebase.sample
-rwxr-xr-x  1 zzc  staff   544 10 21  2019 pre-receive.sample
-rwxr-xr-x  1 zzc  staff  1492 10 21  2019 prepare-commit-msg.sample
-rwxr-xr-x  1 zzc  staff  3610 10 21  2019 update.sample
  • .sample为各个钩子的案例脚本,可以把sample去掉,直接编写shell脚本来执行。
  • 而前端可以用插件husky与pre-commit,来使钩子生效。

husky 注册 git hook

Requires Node >= 10 and Git >= 2.13.0.
  • husky新老版本的配置方式和使用变化较大,老版本请自行升级,详见 husky

1、安装 husky

npm install husky --save-dev

2、编辑 package.json 文件:

{
    "husky": {
        "hooks": {
            "pre-commit": "eslint src/**/*.js"
        }
    },
}

3、尝试 git commit 提交,就会先执行eslint src/**/*.js,代码没有问题才会被真正提交
4、这样每次提交代码,eslint都会检查所有文件,如果报错过多,一定会崩溃

lint-staged 只 Lint 改动代码

lint-staged requires Node.js version 10.13.0 or later.
  • v10.0.0 以后对原始暂存文件的任何新修改都将自动添加到提交中。如果您的任务以前包含一个git add步骤,请删除此步骤,同时运行多个git操作通常会导致错误,详见 lint-staged

1、安装 lint-staged

npm install lint-staged --save-dev

2、新增 package.json 配置:

{
    "lint-staged": {
        "src/**/*.js": "eslint"
    }
}

3、如此husky只负责注册git hook,后续操作交给lint-staged,只对改动的文件执行任务,而且可以很方便
地配置多条命令:

{
    "husky": {
        "hooks": {
            "pre-commit": "lint-staged"
        }
    },
    "lint-staged": {
        "src/**/*.js": ["eslint --fix", "prettier --write"]
    }
}

4、如上,我们提交代码之前,程序会自动修复eslint配置,格式化prettier配置

几点建议

  • 建议代码提交只做检查和测试,拦截问题代码比较好,还是在保存时,自动修复eslint、prettier配置,而且大部分还需要手动修复才行
  • 实在紧急,也可通过git commit -m -n "跳过代码代码预检"跳过检查,慎用
  • 和构建有关的包建议使用--save-dev安装在项目内部
  • 使用VSCode打开项目,path不要嵌套过深,可能导致Lint工具失效
  • 老版本husky lint-staged配置都放在package.json中,现在eslint prettier husky lint-staged都支持多种后缀配置文件,建议采用.js统一格式,也方便拓展:

统一配置文件格式

// .eslintrc.js
module.exports = {
    extends: [
        'alloy',
    ],
};
// .prettierrc.js
module.exports = {
    // 一行最多 100 字符
    printWidth: 100,
    // 使用 4 个空格缩进
    tabWidth: 4,
    // ...
};
// .huskyrc.js
module.exports = {
    'hooks': {
        'pre-commit': "lint-staged"
    }
}
// .lintstagedrc.js
module.exports = {
    "src/**/*.{js,ts}": "eslint"
}
// .stylelintrc.js
module.exports = {
    extends: [
        'stylelint-config-standard',
        'stylelint-config-sass-guidelines',
        'stylelint-config-prettier'
    ],
    plugins: ['stylelint-order', 'stylelint-scss'],
    rules: {
        // ...
    }
};

拓展示例

  • .huskyrc.js
// 数组方式配置多条命令
const tasks = arr => arr.join(' && ')
module.exports = {
  'hooks': {
    'pre-commit': tasks([
      'npm run lint',
      'npm test'
    ])
  }
}
  • .lintstagedrc.js
module.exports = {
    // 如果超过10个暂存文件,则在整个存储库上运行eslint
    '**/*.js?(x)': (filenames) =>
    filenames.length > 10 ? 'eslint .' : `eslint ${filenames.join(' ')}`,
    "*.css": "stylelint",
    "*.scss": "stylelint --syntax=scss",
    // 对ts文件运行tsc,但不传递任何参数
    '**/*.ts?(x)': () => 'tsc -p tsconfig.json --noEmit'
}
查看原文

赞 57 收藏 37 评论 18

ZONE_98F 赞了回答 · 2019-11-26

解决防抖和节流里边的 arguments是谁的啊

假设你现在监听了一个鼠标移动事件:

function handler(e) { console.log(e, this); }

el.onmousemove = handler;

当触发事件时,打印得到事件对象以及当前元素(el)。

现在给事件处理函数加上了防抖:el.onmousemove = debounce(handler)
对于 debounce(handler),返回值是一个函数,所以等同于 el.onmousemove = denouceHandler,只是一个新的事件处理函数而已,它的参数中就会包含事件对象,也就是 arguments 中包含事件对象。

至于 fn.apply(context, args),前面提到 handler 中打印 this 可以拿到正确的值(当前元素),这里即改变 this 的指向。于是乎在加了防抖函数之后去触发事件时,才能保证 fn 内部能够拿到 事件对象 以及 正确的 this

关注 3 回答 4

ZONE_98F 回答了问题 · 2019-11-13

Nuxt.js 中间件刷新不触发的问题

因为代码被当作服务端的代码执行了
在文件里加上当前服务环境的判断

  const isClient = process.client;
    //在客户端判读是否需要登陆
  if (isClient) {
    //只有当前环境在客户端才会执行
  }

关注 6 回答 3

ZONE_98F 发布了文章 · 2019-10-17

Next引入Antd和Sass

这里并不是Next引入Antd或者Sass教程!!
这篇文章讲的是如何在next里同时引入sass和antd

问题起源

我想在Next里引入Antd框架,跟着网上教程将antd引入到框架中后,我又想引入scss但这时候就报错了。
因为next本身支持解析css,网上的文档和教程包括官方文档都是@next/css,或者@next/sass两个插件引用其一来达到支持css和scss的效果。
像这样:

// scss
const withSass = require('@zeit/next-sass')
module.exports = withSass({
})
//css
const withCSS = require('@zeit/next-css')
module.exports = withCSS({
  /* config options here */
})

但是两个插件只能取其一,如果你引入过antd就知道,想使用antd需要在全局import 'antd/dist/antd.css',而引入了这个css文件那么就需要用上next-css插件,用了这个插件我们就用不了next-scss,这就是问题的所在了。

解决办法

在这里就不具体写怎么在next里单独引入antd或者scss了,因为网上的其它教程和官方文档已经跟详细了
我在这里假设你已经会单独引用antd和scss了。
next官方有一个插件能实现我们的需求 :* next-compose-plugins
他能让我们同时引用多个插件

npm install --save next-compose-plugins

next.config.js改成这样

// next.config.js
const withSass = require('@zeit/next-sass')
const withCss = require('@zeit/next-css');
const withPlugins = require("next-compose-plugins");

module.exports = withPlugins([withSass,withCss], {
  webpack: (config) => {
    return config
  },
});

_app.js文件不变

import App from 'next/app'

import 'antd/dist/antd.css'

export default App

然后我在public/assets/css下新建了一个test.scss
QQ截图20191017221330.jpg
这个文件有简单的css样式

.test{
  color: red;
}

pages/index.js将其引入

import { Button } from 'antd';
import '../public/assets/css/test.scss'
...一些代码...
<Button>测试按钮</Button> //antd按钮组件
<h1 className="title test">Welcome to Next.js!</h1> //test.scss文件测试

最后看看效果:
QQ截图20191017222309.jpg
antd的按钮样式有了,test.scss的标题变红样式也有了。
完工!

查看原文

赞 0 收藏 0 评论 1

ZONE_98F 赞了回答 · 2019-09-30

mongoose里面的populate没用?

    Category.findOne({_id:id})
    .populate('lists')

populate应该是字段名字吧

关注 2 回答 1

ZONE_98F 赞了回答 · 2019-09-27

解决mongoose save时,如果数据库不存在同样的数据才执行

確實是使用Collection.update

update(selector, document, options, callback)
Updates documents.

NameTypeDegaultDescription
selectorobjectThe selector for the update operation.
documentobjectThe update document.
optionsobjectnull[optional] Optional settings.
callbackCollection~writeOpCallback[optional] The command result callback

options中有一個upsert屬性(Type: boolean),用於確定這是否是一個 upsert 操作。即但不存在selectop匹配的文檔時,是否插入文檔


name相同則更新,不同則插入:

代碼應該是這樣的:

var urDocument = { // 你想插入的文檔
  name: "joasn",
 other: "ohaedoaduantoduntaodutaod"
};

var MongoClient = require('mongodb').MongoClient,
MongoClient.connect('mongodb://localhost:27017/test', function(err, db) {

  var collection = db.collection('collocation');

  collection.update({name: {$ne: urDocument.name}, {upsert: true}, urDocument);

});

name相同則不作為,不同則插入:

var UrDocument = { // 你想插入的文檔
  name: "joasn",
 other: "ohaedoaduantoduntaodutaod"
};

var MongoClient = require('mongodb').MongoClient,
MongoClient.connect('mongodb://localhost:27017/test', function(err, db) {

  var collection = db.collection('collocation');

  collection.findOne({name: urDocument.name })
      .then(doc => doc ?? collection.insertOne(urDocument));
});

关注 2 回答 2

认证与成就

  • 获得 107 次点赞
  • 获得 20 枚徽章 获得 0 枚金徽章, 获得 3 枚银徽章, 获得 17 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2018-04-17
个人主页被 1.1k 人浏览