vue-cli创建项目时由esLint校验导致报错或警告的问题及解决

 更新时间:2022年05月24日 09:53:02   作者:小雨繁星儿  
这篇文章主要介绍了vue-cli创建项目时由esLint校验导致报错或警告的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

vue-cli创建项目时由esLint校验导致报错或警告

vue-cli创建项目后编写代码控制台一片黄

但不影响代码执行

但是看着就是很不爽啊

到网上搜索了一下这个问题,想起来初始化项目时安装了esLint校验工具

嗯,我看到了很多办法都是下面这样的

1、因为你设置了eslint,如果你不想有规范的js代码,可以重新初始化关掉eslint。

Use ESLint to lint your code? (Y/n) 这一步选no

在bulid/webpack.base.conf.js里面有配置如下:

module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),

点进config.dev.useEslint,发现在config/index.js里配置

useEslint: true, // 改为false即可。

2、万能方法,就是在报错的JS文件中第一行写上 

/* eslint-disable */
Use /* eslint-disable */ to ignore all warnings in a file.

简单粗暴有效率

but 本着 既然人家说我错了这个肯定是不好的啊我得改 这种良好觉悟

我觉得吧,还是应该直面错误勇于改正

so 针对所有的报错信息,进行了一一修改,果然长知识啊,哈哈哈 那我按照他的规范来写我岂不是enenenhahaha

我这是又在做什么梦[○・Д´・ ○]

进入正题,将遇到的报错信息整理了一下

1.ESLint:Strings must use single quote

字符串必须要用单引号引起来

2.Expected indentation of 2 spaces but found 4

eslint不喜欢tab缩进哦,缩进使用两个空格就可以,好的,我现在已经开始要改了~

如果实在是改不了呢,可以↓↓

修改eslint 配置文件 .eslintrc.js

rules: {
   ...
    // 缩进
    // 'indent': 2,
    // 'indent': [2, 2, {"SwitchCase": 1}],
    "indent": [1, 2],
   ...
 }

3.Missing space before value for key 'components’

 这个就是强制属性值前也就是冒号后,习惯性的加一个空格,就可以避免这歌报错提示啦~

4.Newline required at end of file but not found

单文件组件最后的</style>后面要换一行,且只能一行,多了也会报错

其他的就不一一列举的,但是还有些要注意的

{},
{}

{},  {
}

注意:逗号后面也要加一个空格

好啦,以上就是我对这个规范的一些小小心得,后面再碰到再补充~

eslint语法限制项目报错解决

自己从网上找来个实战项目,npm install之后,启动项目,出现了下面这么多的警告和报错,一脸懵逼:

Windows PowerShell
版权所有 (C) Microsoft Corporation。保留所有权利。

PS F:\vue.news-master> npm run dev

> vue.news@2.0.0 dev F:\vue.news-master
> webpack-dev-server --open --inline --progress --config build/webpack.dev.conf.js

 95% emitting

 WARNING  Compiled with 2 warnings                                                                                                                         15:04:08

  ✘  http://eslint.org/docs/rules/indent                   Expected indentation of 0 spaces but found 1
  src\App.vue:15:1
   /*全局引入VueAwesomeSwiper轮播图插件*/
   ^

  ✘  http://eslint.org/docs/rules/spaced-comment           Expected exception block, space or tab after '/*' in comment
  src\App.vue:15:2
   /*全局引入VueAwesomeSwiper轮播图插件*/
    ^

  ✘  http://eslint.org/docs/rules/spaced-comment           Expected space or tab before '*/' in comment
  src\App.vue:15:2
   /*全局引入VueAwesomeSwiper轮播图插件*/
    ^

  ✘  http://eslint.org/docs/rules/no-unused-vars           'VueAwesomeSwiper' is defined but never used
  src\App.vue:16:8
  import VueAwesomeSwiper from 'vue-awesome-swiper';
          ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:16:50
  import VueAwesomeSwiper from 'vue-awesome-swiper';
                                                    ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:17:36
  import 'swiper/dist/css/swiper.css';//这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                      ^

  ✘  http://eslint.org/docs/rules/spaced-comment           Expected space or tab after '//' in comment
  src\App.vue:17:37
  import 'swiper/dist/css/swiper.css';//这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                       ^

  ✘  http://eslint.org/docs/rules/no-multiple-empty-lines  More than 1 blank line not allowed
  src\App.vue:18:1

   ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:20:47
  import AppHead from '@/components/public/Head';
                                                 ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:21:47
  import AppMenu from '@/components/public/Menu';
                                                 ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:22:45
  import AppNav from '@/components/public/Nav';
                                               ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:23:47
  import AppFoot from '@/components/public/Foot';
                                                 ^


✘ 12 problems (12 errors, 0 warnings)


Errors:
  6  http://eslint.org/docs/rules/semi
  3  http://eslint.org/docs/rules/spaced-comment
  1  http://eslint.org/docs/rules/no-multiple-empty-lines
  1  http://eslint.org/docs/rules/no-unused-vars
  1  http://eslint.org/docs/rules/indent


  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:40:36
  import 'swiper/dist/css/swiper.css';这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                      ^

  ✘  http://eslint.org/docs/rules/spaced-comment  Expected space or tab after '///' in comment
  src\components\Select.vue:40:37
  import 'swiper/dist/css/swiper.css';这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                       ^

  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:41:57
  import { swiper, swiperSlide } from 'vue-awesome-swiper';
                                                           ^

  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:43:58
  import { mapState, mapMutations, mapActions } from 'vuex';
                                                            ^


✘ 4 problems (4 errors, 0 warnings)


Errors:
  3  http://eslint.org/docs/rules/semi
  1  http://eslint.org/docs/rules/spaced-comment

You may use special comments to disable some warnings.
Use // eslint-disable-next-line to ignore the next line.
Use /* eslint-disable */ to ignore all warnings in a file.

 WAIT  Compiling...                                                                                                                                        15:05:01
 95% emitting

 WARNING  Compiled with 2 warnings                                                                                                                         15:05:02

  ✘  http://eslint.org/docs/rules/no-unused-vars           'VueAwesomeSwiper' is defined but never used
  src\App.vue:16:8
  import VueAwesomeSwiper from 'vue-awesome-swiper';
          ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:16:50
  import VueAwesomeSwiper from 'vue-awesome-swiper';
                                                    ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:17:36
  import 'swiper/dist/css/swiper.css';//这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                      ^

  ✘  http://eslint.org/docs/rules/spaced-comment           Expected space or tab after '//' in comment
  src\App.vue:17:37
  import 'swiper/dist/css/swiper.css';//这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                       ^

  ✘  http://eslint.org/docs/rules/no-multiple-empty-lines  More than 1 blank line not allowed
  src\App.vue:18:1

   ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:20:47
  import AppHead from '@/components/public/Head';
                                                 ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:21:47
  import AppMenu from '@/components/public/Menu';
                                                 ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:22:45
  import AppNav from '@/components/public/Nav';
                                               ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:23:47
  import AppFoot from '@/components/public/Foot';
                                                 ^


✘ 9 problems (9 errors, 0 warnings)


Errors:
  6  http://eslint.org/docs/rules/semi
  1  http://eslint.org/docs/rules/no-multiple-empty-lines
  1  http://eslint.org/docs/rules/spaced-comment
  1  http://eslint.org/docs/rules/no-unused-vars


  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:40:36
  import 'swiper/dist/css/swiper.css';这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                      ^

  ✘  http://eslint.org/docs/rules/spaced-comment  Expected space or tab after '///' in comment
  src\components\Select.vue:40:37
  import 'swiper/dist/css/swiper.css';这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                       ^

  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:41:57
  import { swiper, swiperSlide } from 'vue-awesome-swiper';
                                                           ^

  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:43:58
  import { mapState, mapMutations, mapActions } from 'vuex';
                                                            ^


✘ 4 problems (4 errors, 0 warnings)


Errors:
  3  http://eslint.org/docs/rules/semi
  1  http://eslint.org/docs/rules/spaced-comment

You may use special comments to disable some warnings.
Use // eslint-disable-next-line to ignore the next line.
Use /* eslint-disable */ to ignore all warnings in a file.

 WAIT  Compiling...                                                                                                                                        15:05:05
 95% emitting

 WARNING  Compiled with 2 warnings                                                                                                                         15:05:06

  ✘  http://eslint.org/docs/rules/no-unused-vars           'VueAwesomeSwiper' is defined but never used
  src\App.vue:16:8
  import VueAwesomeSwiper from 'vue-awesome-swiper';
          ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:16:50
  import VueAwesomeSwiper from 'vue-awesome-swiper';
                                                    ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:17:36
  import 'swiper/dist/css/swiper.css';//这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                      ^

  ✘  http://eslint.org/docs/rules/spaced-comment           Expected space or tab after '//' in comment
  src\App.vue:17:37
  import 'swiper/dist/css/swiper.css';//这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                       ^

  ✘  http://eslint.org/docs/rules/no-multiple-empty-lines  More than 1 blank line not allowed
  src\App.vue:18:1

   ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:20:47
  import AppHead from '@/components/public/Head';
                                                 ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:21:47
  import AppMenu from '@/components/public/Menu';
                                                 ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:22:45
  import AppNav from '@/components/public/Nav';
                                               ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:23:47
  import AppFoot from '@/components/public/Foot';
                                                 ^


✘ 9 problems (9 errors, 0 warnings)


Errors:
  6  http://eslint.org/docs/rules/semi
  1  http://eslint.org/docs/rules/no-multiple-empty-lines
  1  http://eslint.org/docs/rules/spaced-comment
  1  http://eslint.org/docs/rules/no-unused-vars


  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:40:36
  import 'swiper/dist/css/swiper.css';这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                      ^

  ✘  http://eslint.org/docs/rules/spaced-comment  Expected space or tab after '///' in comment
  src\components\Select.vue:40:37
  import 'swiper/dist/css/swiper.css';这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                       ^

  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:41:57
  import { swiper, swiperSlide } from 'vue-awesome-swiper';
                                                           ^

  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:43:58
  import { mapState, mapMutations, mapActions } from 'vuex';
                                                            ^


✘ 4 problems (4 errors, 0 warnings)


Errors:
  3  http://eslint.org/docs/rules/semi
  1  http://eslint.org/docs/rules/spaced-comment

You may use special comments to disable some warnings.
Use // eslint-disable-next-line to ignore the next line.
Use /* eslint-disable */ to ignore all warnings in a file.

 WAIT  Compiling...                                                                                                                                        15:05:07
 95% emitting

 WARNING  Compiled with 2 warnings                                                                                                                         15:05:08

  ✘  http://eslint.org/docs/rules/no-unused-vars           'VueAwesomeSwiper' is defined but never used
  src\App.vue:16:8
  import VueAwesomeSwiper from 'vue-awesome-swiper';
          ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:16:50
  import VueAwesomeSwiper from 'vue-awesome-swiper';
                                                    ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:17:36
  import 'swiper/dist/css/swiper.css';//这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                      ^

  ✘  http://eslint.org/docs/rules/spaced-comment           Expected space or tab after '//' in comment
  src\App.vue:17:37
  import 'swiper/dist/css/swiper.css';//这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                       ^

  ✘  http://eslint.org/docs/rules/no-multiple-empty-lines  More than 1 blank line not allowed
  src\App.vue:18:1

   ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:20:47
  import AppHead from '@/components/public/Head';
                                                 ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:21:47
  import AppMenu from '@/components/public/Menu';
                                                 ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:22:45
  import AppNav from '@/components/public/Nav';
                                               ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:23:47
  import AppFoot from '@/components/public/Foot';
                                                 ^


✘ 9 problems (9 errors, 0 warnings)


Errors:
  6  http://eslint.org/docs/rules/semi
  1  http://eslint.org/docs/rules/no-multiple-empty-lines
  1  http://eslint.org/docs/rules/spaced-comment
  1  http://eslint.org/docs/rules/no-unused-vars


  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:40:36
  import 'swiper/dist/css/swiper.css';这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                      ^

  ✘  http://eslint.org/docs/rules/spaced-comment  Expected space or tab after '///' in comment
  src\components\Select.vue:40:37
  import 'swiper/dist/css/swiper.css';这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                       ^

  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:41:57
  import { swiper, swiperSlide } from 'vue-awesome-swiper';
                                                           ^

  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:43:58
  import { mapState, mapMutations, mapActions } from 'vuex';
                                                            ^


✘ 4 problems (4 errors, 0 warnings)


Errors:
  3  http://eslint.org/docs/rules/semi
  1  http://eslint.org/docs/rules/spaced-comment

You may use special comments to disable some warnings.
Use // eslint-disable-next-line to ignore the next line.
Use /* eslint-disable */ to ignore all warnings in a file.

 WAIT  Compiling...                                                                                                                                        15:05:09
 95% emitting

 WARNING  Compiled with 2 warnings                                                                                                                         15:05:09

  ✘  http://eslint.org/docs/rules/no-unused-vars           'VueAwesomeSwiper' is defined but never used
  src\App.vue:16:8
  import VueAwesomeSwiper from 'vue-awesome-swiper';
          ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:16:50
  import VueAwesomeSwiper from 'vue-awesome-swiper';
                                                    ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:17:36
  import 'swiper/dist/css/swiper.css';//这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                      ^

  ✘  http://eslint.org/docs/rules/spaced-comment           Expected space or tab after '//' in comment
  src\App.vue:17:37
  import 'swiper/dist/css/swiper.css';//这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                       ^

  ✘  http://eslint.org/docs/rules/no-multiple-empty-lines  More than 1 blank line not allowed
  src\App.vue:18:1

   ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:20:47
  import AppHead from '@/components/public/Head';
                                                 ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:21:47
  import AppMenu from '@/components/public/Menu';
                                                 ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:22:45
  import AppNav from '@/components/public/Nav';
                                               ^

  ✘  http://eslint.org/docs/rules/semi                     Extra semicolon
  src\App.vue:23:47
  import AppFoot from '@/components/public/Foot';
                                                 ^


✘ 9 problems (9 errors, 0 warnings)


Errors:
  6  http://eslint.org/docs/rules/semi
  1  http://eslint.org/docs/rules/no-multiple-empty-lines
  1  http://eslint.org/docs/rules/spaced-comment
  1  http://eslint.org/docs/rules/no-unused-vars


  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:40:36
  import 'swiper/dist/css/swiper.css';这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                      ^

  ✘  http://eslint.org/docs/rules/spaced-comment  Expected space or tab after '///' in comment
  src\components\Select.vue:40:37
  import 'swiper/dist/css/swiper.css';这里注意具体看使用的版本是否需要引入样式,以及具体位置。
                                       ^

  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:41:57
  import { swiper, swiperSlide } from 'vue-awesome-swiper';
                                                           ^

  ✘  http://eslint.org/docs/rules/semi            Extra semicolon
  src\components\Select.vue:43:58
  import { mapState, mapMutations, mapActions } from 'vuex';
                                                            ^


✘ 4 problems (4 errors, 0 warnings)


Errors:
  3  http://eslint.org/docs/rules/semi
  1  http://eslint.org/docs/rules/spaced-comment

You may use special comments to disable some warnings.
Use // eslint-disable-next-line to ignore the next line.
Use /* eslint-disable */ to ignore all warnings in a file.

经过百度查询,原来eslint是一个语法检查工具,但是限制很严格,在我的vue文件里面很多空格都会导致红线(红线可以关闭提示),虽然可以关闭,但是在编译的时候老是会跳出来,所以能关闭是最好的了。

关闭方法:在build/webpack.base.conf.js文件中,注释或者删除掉:module->rules中有关eslint的规则:

module: {
  rules: [
    //...(config.dev.useEslint ? [createLintingRule()] : []), // 注释或者删除
    {
      test: /\.vue$/,
      loader: 'vue-loader',
      options: vueLoaderConfig
    },
    ...
    }
  ]
}

然后再重新运行一下npm run dev或者构建命令 npm run build就可以啦。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Vue 使用高德地图添加点标记 + 点击地图获取坐标 + 带搜索(即地理编码 + 逆地理编码)  附完整示例

    Vue 使用高德地图添加点标记 + 点击地图获取坐标 + 带搜索(即地

    这篇文章主要介绍了Vue 使用高德地图添加点标记 + 点击地图获取坐标 + 带搜索(即地理编码 + 逆地理编码)  附完整示例,本文结合示例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2024-01-01
  • 加速vue组件渲染之性能优化

    加速vue组件渲染之性能优化

    这篇文章主要介绍了加速vue组件渲染之性能优化,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • element的el-date-picker组件实现只显示年月日时分效果(不显示秒)

    element的el-date-picker组件实现只显示年月日时分效果(不显示秒)

    最近遇到这样的需求使用element的el-date-picker组件,只显示时分,不显示秒,下面小编给大家分享element的el-date-picker组件实现只显示年月日时分效果,感兴趣的朋友一起看看吧
    2024-08-08
  • vue+koa2实现session、token登陆状态验证的示例

    vue+koa2实现session、token登陆状态验证的示例

    这篇文章主要介绍了vue+koa2实现session、token登陆状态验证的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • VUE使用vue-tree-color组件实现组织架构图并可以动态更新数据的效果

    VUE使用vue-tree-color组件实现组织架构图并可以动态更新数据的效果

    本文主要介绍了如何在Vue中使用vue-tree-color组件实现组织架构图,并详细介绍了如何实现数据的动态加载,在动态加载数据时,要确保数据更新是在Vue的响应式系统能捕获到的情况下进行的
    2024-10-10
  • element select必填项验证回显问题的解决

    element select必填项验证回显问题的解决

    本文主要介绍了element select必填项验证回显问题的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • element table 表格控件实现单选功能

    element table 表格控件实现单选功能

    本文主要介绍了element table 表格控件实现单选功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Vue3中ref与toRef的区别浅析

    Vue3中ref与toRef的区别浅析

    我们知道ref可以用于创建一个响应式数据,而toRef也可以创建一个响应式数据,这篇文章主要给大家介绍了关于Vue3中ref与toRef区别的相关资料,需要的朋友可以参考下
    2021-06-06
  • elementPlus修改主题色以及皮肤设置思路

    elementPlus修改主题色以及皮肤设置思路

    这篇文章主要介绍了elementPlus修改主题色以及皮肤设置思路,具有很好的参考价值,希望对大家有所帮助。
    2023-04-04
  • VUE2实现事件驱动弹窗示例

    VUE2实现事件驱动弹窗示例

    本篇文章主要介绍了VUE2实现事件驱动弹窗示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10

最新评论