- 
                Notifications
    You must be signed in to change notification settings 
- Fork 111
HowToFix
这个问题通常发生在使用 tab 作为缩进,还有部分是由于前面出现的代码中有不恰当的换行或缩进影响的,具体需要使用 fecs 直接检查查看详细的错误信息。
比较容易发现的,是数组内的元素或函数的参数间换行,当内部需要换行时(比如超过 120 字符或排版美观需要),括号内侧也必须换行--左括号之后换行,右括号之前换行。第一个换行的缩进,需要比左括号所在行多一个缩进,右括号所在行的缩进则与左括号所在行的保持一致。
一个特殊的 case 是使用数组作 HTML 字符拼接时,除满足上面所述的缩进外,其它元素间的最多可以差一个缩进(在兄弟节点时可以相等,子节点时增加一个,父节点结束标记减少一个)。如果数组未被识别为 HTML 字符拼接,可以通过增加注释来标识:
// html
var html = [
    objectType,
    functionExpressionType,
    ...
];JS RULE007 [强制] if / else / for / while / function / switch / do / try / catch / finally 关键字后,必须有一个空格。
文字描述已经很清楚,但很多 RD 同学碰到时可能不明白怎么修改,其实只需在以上关键字后加一个空格即可。
对象创建是指直接使用 { 和 } 创建的对象直接量,一般情况下,在 : 前是不允许有空格而在它之后是必须有空格的。特殊情况是当使用 : 作对象字段的对齐排版时,允许 : 前有空格。如果提示某些属性名后、: 前缺少空格,是由于当前对象的属性大部分相对于 : 对齐了。
除了很长的正则和 URL,这个只能通过添加适当的换行和缩进排版来修复。 对于超长的正则和 URL 导致的问题,可以通过注释来屏蔽:
/* eslint-disable max-len */
// 这里是超长的正则或 URL
/* eslint-enable max-len */例如:
if (thisIsALongExpressionForCodeDemoView &&
    thisAnotherLogExpression
)需要改为
if (thisIsALongExpressionForCodeDemoView
    && thisAnotherLogExpression
)IIFE 是指马上执行的函数表达式:
var task = function () {
    // Code
    return result;
}();
var func = (function () {
});
+function () {
    // blablabla
}();必须改成:
// good
var task = (function () {
   // Code
   return result;
})();
var func = function () {
};
(function () {
    // blablabla
})();使用其他语言的同学,可能习惯使用下划线作为命名中单词的分隔符:
var foo_bar = true;这里需要改成:
var fooBar = true;换言之,使用类的构建函数名,必须是大写字母开头。当调用了大写字母开头的函数或方法,但没有使用 new 操作符时,也是不允许的,即便结果正确。
如果是因为使用了第三方的代码,如果加 new 不影响结果的正确性,可以参见 FAQ 中的 《如何修复使用 jQuery 的 DataTable 插件的问题?》,否则需要使用以下方式屏蔽该条规则:
/* eslint-disable new-cap */- 
部分情况同 《JS RULE029 [强制] 类使用Pascal命名法》。
- 
如果方法属性命名是受 RD 接口影响,需要使用以下方式处理: 
/* eslint-disable fecs-camelcase */
// 这里是你的代码
/* eslint-enable fecs-camelcase */- 如果有固定的模式,比如都以 api_开头,可以这样配置:
/* eslint fecs-camelcase: [2, {ignore: ["/^api_/"]}] */
ajax.send({
    api_site: 'baidu',
    api_key: 'djk13-liwfu-bstdj'
});其中 ignore 的取值是字符串数组,字符串以 / 开始和结束时,将按正则字符匹配处理。
- 如果习惯使用 _前缀标识私有属性或方法,则需要增加@private来避免检查:
/**
 * 类描述
 *
 * @class
 * @extends Developer
 */
var Fronteer = function () {
    Developer.call(this);
    /**
     * 属性描述
     *
     * @type {string}
     * @private
     */
    this._level = 'T12';
    // constructor body
};
util.inherits(Fronteer, Developer);
/**
 * 方法描述
 *
 * @private
 * @return {string} 返回值描述
 */
Fronteer.prototype._getLevel = function () {
};意思是除了 String/Number/Boolean 类型的首字母小写,其它类型都大写,如:{Array},{Date},{Function},{Object},{RegExp}。
在文件开始,必须使用 @file 对当前文件作注释:
/**
 * @file 介绍当前文件的说明
 * @author name<email>
 */这种情况通常是漏了某些参数或返回值的注释,可以通过本地运行 fecs 看具体的信息。
对于 Object 类型的参数(比如写配置项时,假设叫 options),想对参数对象的各个字段作注释时,首先不能漏了参数名(options)的注释,然后对于各个字段注释,需要带上 options. 作前缀:
/**
 * 初始化
 *
 * @param {Object} options 配置项
 * @param {boolean} options.disabled 控件的不可用状态
 * @param {(string | HTMLElement)} options.main 控件渲染容器
 * @param {(string | HTMLElement)} options.target 计算弹出层相对位置的目标对象
 * @param {string} options.prefix 控件class前缀,同时将作为main的class之一
 * @param {number} options.index 默认激活的标签索引
 */错误的注释:
/**
 * blablabla
 *
 * @param foo
 * @param bar
 */需要加上参数类型和说明
/**
 * blablabla
 *
 * @param {number} foo 这是 foo 的说明
 * @param {boolean} bar 这是 bar 的说明
 */这是因为使用了非当前文件内定义的全局变量,或者是定义时漏写 var 的变量。
- 
使用了 AMD 的项目,应该通过配置 shim 来把非 AMD 模块伪装成 AMD 模块 require。 
- 
未使用 AMD 的项目,可以把该变量标识为 globals: 
/* globals foo */- 还有一种错误的写法导致出现的全局变量:
var foo = bar = true;正确写法应该是:
var foo = true;
var bar = foo;var foo = true,
    bar = false;需要改为:
var foo = true;
var bar = false;var foo = function () {
    bar();
}
var bar = function () {
    // blablabla
}这种代码的报错主要是因为 bar 的调用在定义之前所致。解决的办法很简单,把 bar 的定义提前:
var bar = function () {
    // blablabla
}
var foo = function () {
    bar();
}也可以把 bar 改成函数声明:
var foo = function () {
    bar();
}
function bar() {
    // blablabla
}当判断 foo 为 null 或 undefined 时,使用 foo == null,不是 foo == undefined。
其实就是为 parseInt 指定第二个参数:
// bad
parseInt(str);
// good
parseInt(str, 10);主要是防止低级浏览器中的 0 开头的字符默认识别为 8 进制问题:
parseInt('010'); // 8
parseInt('010', 10); // 10单引号输入时可以少按一个 Shift 键,而在拼写 HTML 字符串时,还可以保留 HTML 属性中的双引号,避免使用 \ 转义嵌套的双引号。
var foo = 'bar';这两个问题通常和《JS RULE030 [强制] 类的 方法 / 属性 使用 Camel命名法》相关。
当属性中使用下划线时,不需要添加双引号,但是此时会报 030 的问题。正确的做法是除非有某一属性名出现关键字或非字母数字和 $、_ 之外字符时,可以全部添加引号,否则不允许使用引号。
// 不允许添加引号
var foo = {
    'bar': true,
    'baz': false
};// 必须全部添加引号
var foo = {
    'bar': true,
    'foo-baz': false
};从 Cooder 或 eagle 报的描述中,%s 没有替换为具体的错误信息,所以需要本地运行 fecs 来获取详细的信息再作修改。
和 RULE998 问题一样,需要本地运行 fecs 来获取详细的信息再作修改。
该错误源于对未闭合的标签的检查,示例如下:
<!-- good -->
<ul>
    <li>first</li>
    <li>second</li>
</ul>
<!-- bad -->
<ul>
    <li>first
    <li>second
</ul>不过大多数时候,报告该错误都是因为文件内容并非单纯HTML代码,而是某种模板,模板语法破坏了HTML本身的结构,导致一些HTML标签被认为没有正确闭合。对于模板文件,建议的做法是修改文件后缀名为.tpl或.tmpl,避免HTML规范检查。如果因为某些原因需要使用.html后缀名,可以使用.tpl.html,也可以避免检查。
这两个字面上很好理解,要求head中第一个子元素为指定字符编码的meta标签,紧随其后是title标签。
常见的不规范情况包括:
- 
meta标签未使用精简形式 精简形式: <meta charset="UTF-8"> 非精简形式(不符规范): <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> 
- 
meta或title标签位置不正确,规范明确要求了meta作为head的第一个直接子元素,且title紧随其后
当错误超出以上范围,并且认为不需要修复代码,可按以下步骤处理:
- 
安装 fecs
- 
运行 fecs [files] --rule,记下打印出的错误行尾显示的规则名。
- 
在文件头部使用 /* linter-disable ruleName */来屏蔽对应的规则。其中,JavaScript、CSS 和 HTML 文件分别对应的 linter 为 eslint、csshint 和 htmlcs。
- 
如果只需要对指定代码块作规则屏蔽,可以在代码块结束后使用 /* linter-enable ruleName */来恢复规则检查。
注意:在 CSS 与 HTML 中,当省略 ruleName 时,意味着关闭对当前文件的检查,但 ruleName 不存在时,则忽略该条设置。
// Learn TypeScript: // - https://docs.cocos.com/creator/manual/en/scripting/typescript.html // Learn Attribute: // - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html // Learn life-cycle callbacks: // - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html
import AssetMgr from './framework/AssetMgr'; import AudioMgr from './framework/AudioMgr'; import EventMgr from './framework/EventMgr'; import ObjectPoolMgr from './framework/ObjectPoolMgr'; import TimerMgr from './framework/TimerMgr'; import UIMgr from './framework/UIMgr'; import Instance from './framework/utils/Instance'; import PropMgr from './logic/common/PropMgr'; import UserInfo from './logic/common/UserInfo'; import ArtDataMgr from './logic/data/ArtDataMgr'; import ConfigArtGroupMgr from './logic/data/ConfigArtGroupMgr'; import ConfigArtMgr from './logic/data/ConfigArtMgr'; import ConfigMgr from './logic/data/ConfigMgr'; import SaveDataMgr from './logic/data/SaveDataMgr'; import HttpLogicMgr from './logic/net/HttpLogicMgr'; import GridMgr from './logic/painting/GridMgr'; import PaintingGridDataMgr from './logic/painting/PaintingGridDataMgr'; import PaintingPaletteDataMgr from './logic/painting/PaintingPaletteDataMgr'; import StarBlinkEffectMgr from './logic/ui/effects/StarBlinkEffectMgr';
const { ccclass, property } = cc._decorator;
@ccclass export default class App extends cc.Component { static UIRoot: cc.Node = null; static timerMgr: TimerMgr = null; static eventMgr: EventMgr = null; static assetMgr: AssetMgr = null; static uiMgr: UIMgr = null; static poolMgr: ObjectPoolMgr = null; static httpMgr: HttpLogicMgr = null; static audioMgr: AudioMgr = null; static userInfo: UserInfo = null; static gridMgr: GridMgr = null; static paintingPaletteDataMgr: PaintingPaletteDataMgr = null; static saveDataMgr: SaveDataMgr = null; static paintingGridDataMgr: PaintingGridDataMgr = new PaintingGridDataMgr(); static propMgr: PropMgr = null; static artDataMgr: ArtDataMgr = null; private static configMgr: ConfigMgr = null; static configArtMgr: ConfigArtMgr = null; static configArtGroupMgr: ConfigArtGroupMgr = null;; /** * 测试网络开关 / static isOpenNetwork: boolean = true; /* * 是否是链接本地 / static isLocalNetwork: boolean = true; /* * 是否开启网络log */ static isOpenNetworkLog: boolean = true;
async onLoad() {
    App.UIRoot = cc.find('Canvas/UIRoot');
    // cc.debug.setDisplayStats(false);
    // cc.game.setFrameRate(30)
    // 注册单例
    App.eventMgr = Instance.get(EventMgr);
    App.timerMgr = Instance.get(TimerMgr);
    App.assetMgr = Instance.get(AssetMgr);
    App.poolMgr = Instance.get(ObjectPoolMgr);
    App.httpMgr = Instance.get(HttpLogicMgr);
    App.audioMgr = Instance.get(AudioMgr);
    App.userInfo = Instance.get(UserInfo);
    App.paintingGridDataMgr = Instance.get(PaintingGridDataMgr);
    App.paintingPaletteDataMgr = Instance.get(PaintingPaletteDataMgr);
    App.propMgr = Instance.get(PropMgr);
    App.saveDataMgr = Instance.get(SaveDataMgr);
    App.artDataMgr = Instance.get(ArtDataMgr);
    App.gridMgr = Instance.get(GridMgr);
    /** ----初始化数据库 */
    const dbOk = await App.saveDataMgr.init(UserInfo.PaintingDataKey);// 增加新的数据表需要同时修改版本号
    console.log('dbOk = ' + dbOk);
    // App.userInfo.clearAllDatas()
    /** ----加载数据 */
    App.userInfo.loadData();
    /** ----初始化ui管理 */
    // 注册事件监听
    App.eventMgr.registerOwner(UIMgr);
    // 初始化ui管理类
    App.uiMgr = Instance.get(UIMgr).init(App.UIRoot);
    /** ----加载art数据 编辑器生成的 */
    await App.artDataMgr.loadData();
    await this.cacheViews(['PaintingView']);
    /** ----初始化configs */
    App.configMgr = Instance.get(ConfigMgr);
    await App.configMgr.loadConfig('dataConfigs');
    App.configArtGroupMgr = Instance.get(ConfigArtGroupMgr).init(App.configMgr.getTable('artGroup'));
    App.configArtMgr = Instance.get(ConfigArtMgr).init(App.configMgr.getTable('art'));
    /** ----初始化tile缓存 */
    let prefab = await App.assetMgr.load('prefabs/TiledTile', cc.Prefab);
    App.poolMgr.createObjectPool('TiledTile', (prefab as cc.Prefab), 110 * 110 * 4);
    prefab = await App.assetMgr.loadPrefab('prefabs/StarArrayEffect');
    App.poolMgr.createObjectPool('StarArrayEffect', (prefab as cc.Prefab), 110 * 110 * 4);
    prefab = await App.assetMgr.loadPrefab('prefabs/StarBlinkEffect');
    App.poolMgr.createObjectPool('StarBlinkEffect', (prefab as cc.Prefab), 300);
    /** ----进入游戏 */
    App.uiMgr.showView('HomeBottomView', 0);
    cc.game.setFrameRate(30);
}
private async cacheViews(names: string[]) {
    for (let index = 0; index < names.length; index++) {
        const name = names[index];
        const Prefab = await App.assetMgr.load(`ui/${name}`, cc.Prefab);
        App.poolMgr.createObjectPool(name, (Prefab as cc.Prefab), 1);
    }
}
update(dt) {
    App.timerMgr.update(dt);
}
/**
 * 显示绘制界面
 * @param data
 */
static async GotoPainting(data: any) {
    App.userInfo.paintingRecord(data.id);
    App.userInfo.saveData();
    await App.uiMgr.showView('PaintingView', data);
    App.uiMgr.hideView('HomeBottomView');
    App.uiMgr.hideView('CutImageView');
    // cc.game.setFrameRate(60);
}
/**
 * 回到主界面
 */
static async GotoHome() {
    if (!App.uiMgr.isViewShow('HomeBottomView')) {
        await App.uiMgr.showView('HomeBottomView');
    }
}
}