commander.js使用及源码分析

commander.js

commander是一个轻巧的nodejs模块,提供了用户命令行输入和参数解析强大功能。

commander的特性:

  • 自记录代码
  • 自动生成帮助
  • 合并短参数
  • 默认选项
  • 强制选项​​
  • 命令解析
  • 提示符

安装

npm install commander

使用

在文件中引入commander,可以通过直接引入一个program对象或者创建一个实例的方式进行使用。

const { program } = require('commander');
program.version("v1.0.0");
const { Command } = require('commander');
const program = new Command();
program.version("v1.0.0");

通过查看源码可以得知program其实就是一个刚创建的实例,可以更明确地访问全局命令。

源码片段:

exports = module.exports = new Command();
exports.program = exports;

exports.Command = Command;

option选项

Commander 使用.option()方法来定义选项,同时可以附加选项的简介。每个选项可以定义一个短选项名称(-后面接单个字符)和一个长选项名称(--后面接一个或多个单词),使用逗号、空格或|分隔。

语法:
options(flags, description, fn, defaultValue)

commander.option(
    "-f, --filename [filename]",
    "The filename to use when reading from stdin. This will be used in source-maps, errors etc."
);

源码解析:

lib\command.js option()

采用柯里化写法, 实际调用的是_optionsEx()方法

  options(flags, description, fn, defaultValue) {
    return this._optionEx({}, flags, description, fn, defaultValue);
  }

_optionsEx(), 创建一个options实例,fn可以是函数、正则等形式,需要注意的是尽量不要使用正则形式,自 Commander v7 起,该功能不再推荐使用。

  _optionEx(config, flags, description, fn, defaultValue) {
    // 创建一个option实例
    const option = this.createOption(flags, description);
    if (typeof fn === "function") {
      option.default(defaultValue).argParser(fn);
    } else if (fn instanceof RegExp) {
      // deprecated
      ...
    } else {
      option.default(fn);
    }

    return this.addOption(option);
  }

Option构造函数中,会调用一个splitOptionFlags()方法,用于解析长、断标识,比如说-m,--mixed attributeName()会返回一个camelcase的字符,例如--file-name会被解析成fileName

通过空格、|,来切割出不同的字符。

function splitOptionFlags(flags) {
  let shortFlag;
  let longFlag;
  const flagParts = flags.split(/[ |,]+/);
  if (flagParts.length > 1 && !/^[[<]/.test(flagParts[1]))
    shortFlag = flagParts.shift();
  longFlag = flagParts.shift();
  if (!shortFlag && /^-[^-]$/.test(longFlag)) {
    shortFlag = longFlag;
    longFlag = undefined;
  }
  return { shortFlag, longFlag };
}

同时,根据flags中的字符进行判断是否有设置接收参数。 表示执行该命令时必须传入一个参数,表示可接受多个参数,[value]表示可配置参数。

this.required = flags.includes("<"); 
this.optional = flags.includes("[");
this.variadic = /\w\.\.\.[>\]]$/.test(flags)

在创建了一个option对象后,将其放入addOption()中进行处理,该方法会对option进行注册、监听等操作。

  addOption(option) {
    const oname = option.name();
    const name = option.attributeName();
    // 注册
    this.options.push(option);

    const handleOptionValue = (val, invalidValueMessage, valueSource) => {
      // ...
    };

    this.on("option:" + oname, (val) => {
      const invalidValueMessage = `error: option '${option.flags}' argument '${val}' is invalid.`;
      handleOptionValue(val, invalidValueMessage, "cli");
    });

    if (option.envVar) {
      this.on("optionEnv:" + oname, (val) => {
        const invalidValueMessage = `error: option '${option.flags}' value '${val}' from env '${option.envVar}' is invalid.`;
        handleOptionValue(val, invalidValueMessage, "env");
      });
    }

    return this;
  }

Command继承了node中的事件模块EventEmitter实现对option的监听和触发。

在写好option配置后,需要调用program.parse(process.argv)方法对用户的输入进行解析。

parse(argv, parseOptions)

parse(argv, parseOptions) {
  const userArgs = this._prepareUserArgs(argv, parseOptions);
  this._parseCommand([], userArgs);

  return this;
}

_prepareUserArgvs方法中解析读取用户的输入。process.argv获取的数组前两个元素分别是node安装地址跟运行的script路径,后边的才是用户的输入,因此需要先过滤掉这两个。同时还支持多个argv约定。

_prepareUserArgs(argv, parseOptions) {
  parseOptions = parseOptions || {};
  this.rawArgs = argv.slice();

  let userArgs;
  switch (parseOptions.from) {
    case undefined:
    case 'node':
      this._scriptPath = argv[1];
      userArgs = argv.slice(2);
      break;
    case 'electron':
      if (process.defaultApp) {
        this._scriptPath = argv[1];
        userArgs = argv.slice(2);
      } else {
        userArgs = argv.slice(1);
      }
      break;
    case 'user':
      userArgs = argv.slice(0);
      break;
    default:
      throw new Error(
        `unexpected parse option { from: '${parseOptions.from}' }`
      );
  }
  if (!this._scriptPath && require.main) {
    this._scriptPath = require.main.filename;
  }

  this._name =
    this._name ||
    (this._scriptPath &&
      path.basename(this._scriptPath, path.extname(this._scriptPath)));

  return userArgs;
}

在获取了用户输入后,就是对这些参数进行解析。

_parseCommand()

_parseCommand(operands, unknown) {
    const parsed = this.parseOptions(unknown);
    // command部分下边继续讲解
}

parseOptions读取输入的配置

parseOptions(argv) {
  const operands = [];
  const unknown = [];
  let dest = operands;
  const args = argv.slice();

  // 判断是否是option配置, 必须要有一个-开头
  function maybeOption(arg) {
    return arg.length > 1 && arg[0] === '-';
  }

  let activeVariadicOption = null;
  // 逐步读取配置
  while (args.length) {
    const arg = args.shift();
    // --终止读取 也就是说 -- 后边的配置并不会生效
    // 例如 node src/index.js -  --number 1 2 3 -- -c a b
    // -c其实没有用
    if (arg === '--') {
      if (dest === unknown) dest.push(arg);
      dest.push(...args);
      break;
    }

    // 处理多参数情况
    if (activeVariadicOption && !maybeOption(arg)) {
      // 当触发这个监听时会执行handleOptionValue,里边会判断variadic的值将所有的参数放进一个数组中
      this.emit(`option:${activeVariadicOption.name()}`, arg);
      continue;
    }
    activeVariadicOption = null;

    if (maybeOption(arg)) {
      // 查看是否已经配置有该命令
      const option = this._findOption(arg);
      if (option) {
          // 前边提到的当配置option时如果有配置  必填参数,那么该option的required值为true
        if (option.required) {
            // 读取value
          const value = args.shift();
          if (value === undefined) this.optionMissingArgument(option);
          // 触发监听方法
          this.emit(`option:${option.name()}`, value);
        // 配置了可选参数
        } else if (option.optional) {
          let value = null;
          if (args.length > 0 && !maybeOption(args[0])) {
            value = args.shift();
          }
          this.emit(`option:${option.name()}`, value);
        } else {
          // boolean flag
          this.emit(`option:${option.name()}`);
        }
        // 前面提到当配置的option中存在 ...> 如时,variadic值为true
        activeVariadicOption = option.variadic ? option : null;
        continue;
      }
    }

    // 组合flag, 比如像 -abc , 会遍历判断 -a -b -c是否是配置过的option
    if (arg.length > 2 && arg[0] === '-' && arg[1] !== '-') {
      // 拆解组合
      const option = this._findOption(`-${arg[1]}`);
      if (option) {
        if (
          option.required ||
          (option.optional && this._combineFlagAndOptionalValue)
        ) {
          this.emit(`option:${option.name()}`, arg.slice(2));
        } else {
          this.emit(`option:${option.name()}`);
          args.unshift(`-${arg.slice(2)}`);
        }
        continue;
      }
    }

    // 解析--foo=bar传参格式
    if (/^--[^=]+=/.test(arg)) {
      const index = arg.indexOf('=');
      const option = this._findOption(arg.slice(0, index));
      if (option && (option.required || option.optional)) {
        this.emit(`option:${option.name()}`, arg.slice(index + 1));
        continue;
      }
    }

    if (maybeOption(arg)) {
      dest = unknown;
    }

    // 解析command 下面在讲解
    dest.push(arg);
  }

  return { operands, unknown };
}

从上面的源码解析中可以总结如下:

  1. 多个短选项可以合并简写,最后一个选项可以附加参数, 比如-a -b -c 1可以写成-abc 1
  2. --可以标记选项的结束,后续的参数均不会被命令解释,可以正常使用。
  3. 可以通过=传参
  4. 可以传递多个参数

常用选项类型

  1. boolean型, 选项无需配置参数, 通常我们使用的都是此类型。
  2. 设置参数(使用尖括号声明在该选项后,如--expect ),如果在命令行中不指定具体的选项及参数,则会被定义为undefined
const { Command } = require('commander');
const program = new Command();

program.option('-e --example', 'this is a boolean type option');

program.option('-t --type ', 'must set an param or an error will occur');

program.parse(process.argv);
console.log(program.opts());

eg.

node index.js -e
{ example: true }

node index.js -t
error: option '-t --type ' argument missing


node index.js -t a
{ type: 'a' }
  1. 取反, 可以定义一个以 no- 开头的 boolean长选项。在命令行中使用该选项时,会将对应选项的值置为 false。当只定义了带 no- 的选项,未定义对应不带 no- 的选项时,该选项的默认值会被置为 true值。
program.option('--no-example', 'no example');
node index.js --no-example
{ example: false }

源码解析:

在配置了option之后,会对该命令进行监听,执行该flag会触发handleOptionValue方法,根据用户是否有设置取反或者有默认值,来设置该option的值

handleOptionValue

const handleOptionValue = (val, invalidValueMessage, valueSource) => {
  const oldValue = this.getOptionValue(name);
  
  // 参数处理这部分放在自定义选项部分讲解
  // .. 

  if (typeof oldValue === 'boolean' || typeof oldValue === 'undefined') {
    if (val == null) {
      this.setOptionValueWithSource(
        name,
        // 是否取反,取反的话值为false, 不取反就判断是否有值,没有就赋值为true
        option.negate ? false : defaultValue || true,
        valueSource
      );
    } else {
      this.setOptionValueWithSource(name, val, valueSource);
    }
  } else if (val !== null) {
    this.setOptionValueWithSource(
      name,
      option.negate ? false : val,
      valueSource
    );
  }
};
  1. 可选参数 (--optional [value]), 该选项在不带参数时可用作 boolean 选项,在带有参数时则从参数中得到值。
program.option('-f [filename]', 'optional');
node index.js -f
{ f: true }

node index.js -f index.js
{ f: 'index.js' }
  1. 必填选项
    通过.requiredOption()方法可以设置选项为必填。必填选项要么设有默认值,要么必须在命令行中输入,对应的属性字段在解析时必定会有赋值。该方法其余参数与.option()一致。
program.requiredOption('-r --required ', 'must');
node index.js   
error: required option '-r --required ' not specified

当然可以设置一个默认值

program.requiredOption('-r --required ', 'must''a');
node index.js   
{ required: 'a' }
  1. 变长参数选项
    定义选项时,可以通过使用...来设置参数为可变长参数。在命令行中,用户可以输入多个参数,解析后会以数组形式存储在对应属性字段中。在输入下一个选项前(---开头),用户输入的指令均会被视作变长参数。与普通参数一样的是,可以通过--标记当前命令的结束。
program.option('-n ', 'set numbers');
program.option('-c ', 'set chars');
node index.js -n 1 2 3 4 -c a b c
{ n: [ '1', '2', '3', '4' ], c: [ 'a', 'b', 'c' ] }
  1. 版本
    .version()方法可以设置版本,其默认选项为-V--version,设置了版本后,命令行会输出当前的版本号。
program.version('v1.0.0')

版本选项也支持自定义设置选项名称,可以在.version()方法里再传递一些参数(长选项名称、描述信息),用法与.option()方法类似。

program.version('v1.0.0', '-a --aversion', 'current version');

源码解析

version方法其实很简单,就是判断用户配置version信息时有没有自定义信息,比如说启动命令这些。之后就是创建一个option注册后监听。

version(str, flags, description) {
  if (str === undefined) return this._version;
  this._version = str;
  flags = flags || '-V, --version';
  description = description || 'output the version number';
  const versionOption = this.createOption(flags, description);
  this._versionOptionName = versionOption.attributeName();
  this.options.push(versionOption);
  this.on('option:' + versionOption.name(), () => {
    this._outputConfiguration.writeOut(`${str}\n`);
    this._exit(0, 'commander.version', str);
  });
  return this;
}

  1. 使用addOption方法
    大多数情况下,选项均可通过.option()方法添加。但对某些不常见的用例,也可以直接构造Option对象,对选项进行更详尽的配置。
program
  .addOption(
    new Option('-t, --timeout ', 'timeout in seconds').default(
      60,
      'one minute'
    )
  )
  .addOption(
    new Option('-s, --size ', 'size').choices([
      'small',
      'medium',
      'large',
    ])
  );
node index.js -s small
{ timeout: 60, size: 'small' }

node index.js -s mini
error: option '-s, --size ' argument 'mini' is invalid. Allowed choices are small, medium, large.

源码解析:就是添加一个fn在传入值的时候判断一下值就可以。

function choices(values) {
  this.argChoices = values;
  this.parseArg = (arg, previous) => {
    if (!values.includes(arg)) {
      throw new InvalidArgumentError(
        `Allowed choices are ${values.join(', ')}.`
      );
    }
    if (this.variadic) {
      return this._concatValue(arg, previous);
    }
    return arg;
  };
  return this;
}
  1. 自定义选项
    选项的参数可以通过自定义函数来处理,该函数接收两个参数,即用户新输入的参数值和当前已有的参数值(即上一次调用自定义处理函数后的返回值),返回新的选项参数值。 也就是option中的第三个参数。第四个参数就是初始值

自定义函数适用场景包括参数类型转换,参数暂存,或者其他自定义处理的场景。

program.option(
  '-f --float ',
  'process float argument',
  (value, previous) => {
    return Number(value) + previous;
  },
  2
);
node index.js -f 3
{ float: 5 }

源码解析:

const handleOptionValue = (val, invalidValueMessage, valueSource) => {
  const oldValue = this.getOptionValue(name);
  
  // 当配置了option的第三个参数
  if (val !== null && option.parseArg) {
    try {
      val = option.parseArg(
        val,
        // defaultValue为第四个参数
        oldValue === undefined ? defaultValue : oldValue
      );
    } catch (err) {
      if (err.code === "commander.invalidArgument") {
        const message = `${invalidValueMessage} ${err.message}`;
        this._displayError(err.exitCode, err.code, message);
      }
      throw err;
    }

  // 处理多参数情况
  } else if (val !== null && option.variadic) {
    val = option._concatValue(val, oldValue);
  }

  // ...
  // 查看取反部分讲解
}

配置命令

通过.command().addCommand()可以配置命令,有两种实现方式:为命令绑定处理函数,或者将命令单独写成一个可执行文件。子命令支持嵌套。

.command()的第一个参数为命令名称。命令参数可以跟在名称后面,也可以用.argument()单独指定。参数可为必选的(尖括号表示)、可选的(方括号表示)或变长参数(点号表示,如果使用,只能是最后一个参数)。

program
  .command('clone  [destination]')
  .description('clone a repository into a newly created directory')
  .action((source, destination) => {
    console.log('clone command called');
  });

Command对象上使用.argument()来按次序指定命令参数。该方法接受参数名称和参数描述。参数可为必选的(尖括号表示,例如)或可选的(方括号表示,例如[optional])。

program
  .command('login')
  .description('login')
  .argument('', 'user')
  .argument('[password]', 'password', 'no password')
  .action((username, password) => {
    console.log(`login, ${username} - ${password}`);
  });

在参数名后加上...来声明可变参数,且只有最后一个参数支持这种用法。可变参数会以数组的形式传递给处理函数。

program
  .command('readFile')
  .description('read multiple file')
  .argument('', 'user')
  .argument('[password]', 'password', 'no password')
  .argument('')
  .action((username, password, args) => {
    args.forEach((dir) => {
      console.log('rmdir %s', dir);
    });
    console.log(`username: ${username}, pass: ${password}, args: ${args}`);
  });

源码解析: 新建一个command

command(nameAndArgs, actionOptsOrExecDesc, execOpts) {
  let desc = actionOptsOrExecDesc;
  let opts = execOpts;
  if (typeof desc === 'object' && desc !== null) {
    opts = desc;
    desc = null;
  }
  opts = opts || {};
  // 解析获取输入的命令及参数
  const [, name, args] = nameAndArgs.match(/([^ ]+) *(.*)/);

  // 创建一个command
  const cmd = this.createCommand(name);
  if (desc) {
    cmd.description(desc);
    cmd._executableHandler = true;
  }
  if (opts.isDefault) this._defaultCommandName = cmd._name;
  cmd._hidden = !!(opts.noHelp || opts.hidden);
  cmd._executableFile = opts.executableFile || null;
  // 添加参数
  if (args) cmd.arguments(args);
  this.commands.push(cmd);
  cmd.parent = this;
  // 继承属性
  cmd.copyInheritedSettings(this);

  if (desc) return this;
  return cmd;
}

action用于注册命令回调。

action(fn) {
  const listener = (args) => {
    const expectedArgsCount = this._args.length;
    const actionArgs = args.slice(0, expectedArgsCount);
    if (this._storeOptionsAsProperties) {
      actionArgs[expectedArgsCount] = this;
    } else {
      actionArgs[expectedArgsCount] = this.opts();
    }
    actionArgs.push(this);

    return fn.apply(this, actionArgs);
  };
  this._actionHandler = listener;
  return this;
}

接下来就是如何解析执行命令部分了。还记得我们之前解析option时的流程嘛
parse() -> _parseCommand(), 在parseOptions方法中,我们还剩余了处理命令部分代码,现在来看一下。

源码解析:

parseOptions(argv) {
  const operands = [];
  const unknown = [];
  let dest = operands;
  const args = argv.slice();

  while (args.length) {
    // 解析option部分
    // ...

    // 当开启了enablePositionalOptions后, 会将命令后边的参数全部定义为未知参数,而不是命令选项,同时如果想要在子命令中启动enablePositionalOptions,需要在父命令中先开启。
    if (
      (this._enablePositionalOptions || this._passThroughOptions) &&
      operands.length === 0 &&
      unknown.length === 0
    ) {
      if (this._findCommand(arg)) {
        operands.push(arg);
        if (args.length > 0) unknown.push(...args);
        break;
      } else if (
        arg === this._helpCommandName &&
        this._hasImplicitHelpCommand()
      ) {
        operands.push(arg);
        if (args.length > 0) operands.push(...args);
        break;
      } else if (this._defaultCommandName) {
        unknown.push(arg);
        if (args.length > 0) unknown.push(...args);
        break;
      }
    }

    if (this._passThroughOptions) {
      dest.push(arg);
      if (args.length > 0) dest.push(...args);
      break;
    }
    dest.push(arg);
  }
  return { operands, unknown };
}

没有开启enablePositionalOptions配置,命令及后边的参数都会保存在operands数组中,当开启后,命令后边的参数都会变成unknown

在解析了用户输入的参数后继续往下执行_parseCommand方法

_parseCommand(operands, unknown) {
  // 解析配置
  const parsed = this.parseOptions(unknown);
  this._parseOptionsEnv(); // after cli, so parseArg not called on both cli and env
  operands = operands.concat(parsed.operands);
  unknown = parsed.unknown;
  this.args = operands.concat(unknown);

  // 匹配找到命令, 使用子进程运行命令
  if (operands && this._findCommand(operands[0])) {
    return this._dispatchSubcommand(operands[0], operands.slice(1), unknown);
  }

  // 没找到命令就判断一下是否有帮助命令, 而且用户输入的第一个参数是help
  if (this._hasImplicitHelpCommand() && operands[0] === this._helpCommandName) {
    // 有且只有个命令
    if (operands.length === 1) {
      this.help();
    }
    // 执行第二条命令
    return this._dispatchSubcommand(operands[1], [], [this._helpLongFlag]);
  }
  // 帮助命令也没有找到或者用户输入的第一个参数未知但是存在一个默认名字
  if (this._defaultCommandName) {
    outputHelpIfRequested(this, unknown); // Run the help for default command from parent rather than passing to default command
    return this._dispatchSubcommand(
      this._defaultCommandName,
      operands,
      unknown
    );
  }
  // ...

  const commandEvent = `command:${this.name()}`;
  // 存在command处理器
  if (this._actionHandler) {
    checkForUnknownOptions();
    // 处理参数
    this._processArguments();

    let actionResult;
    actionResult = this._chainOrCallHooks(actionResult, 'preAction');
    actionResult = this._chainOrCall(actionResult, () =>
      this._actionHandler(this.processedArgs)
    );
    // 触发父命令
    if (this.parent) this.parent.emit(commandEvent, operands, unknown); // legacy
    actionResult = this._chainOrCallHooks(actionResult, 'postAction');
    return actionResult;
  }
  // 触发父监听器
  if (this.parent && this.parent.listenerCount(commandEvent)) {
    checkForUnknownOptions();
    this._processArguments();
    this.parent.emit(commandEvent, operands, unknown);
  // 处理参数
  } else if (operands.length) {
    if (this._findCommand('*')) {
      return this._dispatchSubcommand('*', operands, unknown);
    }
    if (this.listenerCount('command:*')) {
      this.emit('command:*', operands, unknown);
    } else if (this.commands.length) {
      this.unknownCommand();
    } else {
      checkForUnknownOptions();
      this._processArguments();
    }
  // 不存在命令
  } else if (this.commands.length) {
    checkForUnknownOptions();
    this.help({ error: true });
  } else {
    checkForUnknownOptions();
    this._processArguments();
  }
}

到此,整个解析过程就完成了。

声明统一参数

命令处理函数的参数,为该命令声明的所有参数,除此之外还会附加两个额外参数:一个是解析出的选项,另一个则是该命令对象自身。

program
  .argument('')
  .option('-t, --title '</span><span class="token punctuation">,</span> <span class="token string">'title to use before name'</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">option</span><span class="token punctuation">(</span><span class="token string">'-d, --de'</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">action</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">name<span class="token punctuation">,</span> options<span class="token punctuation">,</span> command</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>options<span class="token punctuation">)</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span><span class="token function">name</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> 
  <h3>帮助信息</h3> 
  <p>帮助信息是 <code>Commander</code> 基于你的程序自动生成的,默认的帮助选项是<code>-h,--help</code>。</p> 
  <pre><code class="prism language-bash">node index.js -h
Usage: index <span class="token punctuation">[</span>options<span class="token punctuation">]</span>

Options:
  -h, --help  display <span class="token builtin class-name">help</span> <span class="token keyword">for</span> <span class="token builtin class-name">command</span>
</code></pre> 
  <p><code>源码解析:</code><br> <code>commander.js</code>提供了一个<code>help</code>类,但是它的方法都是静态的,允许被覆盖。在<code>command</code>类中有一个<code>createHelp</code>方法,通过<code>Object.assign()</code>方法覆盖<code>help</code>的原始方法。</p> 
  <pre><code class="prism language-js"><span class="token function">createHelp</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> Object<span class="token punctuation">.</span><span class="token function">assign</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Help</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">configureHelp</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> 
  <p><code>formatHelp</code>生成帮助文字,解析处理设置的<code>command</code>、<code>option</code>、<code>argument</code>等</p> 
  <pre><code class="prism language-js"><span class="token function">formatHelp</span><span class="token punctuation">(</span><span class="token parameter">cmd<span class="token punctuation">,</span> helper</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> termWidth <span class="token operator">=</span> helper<span class="token punctuation">.</span><span class="token function">padWidth</span><span class="token punctuation">(</span>cmd<span class="token punctuation">,</span> helper<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> helpWidth <span class="token operator">=</span> helper<span class="token punctuation">.</span>helpWidth <span class="token operator">||</span> <span class="token number">80</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> itemIndentWidth <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> itemSeparatorWidth <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
  <span class="token comment">// 格式化</span>
  <span class="token keyword">function</span> <span class="token function">formatItem</span><span class="token punctuation">(</span><span class="token parameter">term<span class="token punctuation">,</span> description</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>description<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> fullText <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>term<span class="token punctuation">.</span><span class="token function">padEnd</span><span class="token punctuation">(</span>
        termWidth <span class="token operator">+</span> itemSeparatorWidth
      <span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> helper<span class="token punctuation">.</span><span class="token function">wrap</span><span class="token punctuation">(</span>
        fullText<span class="token punctuation">,</span>
        helpWidth <span class="token operator">-</span> itemIndentWidth<span class="token punctuation">,</span>
        termWidth <span class="token operator">+</span> itemSeparatorWidth
      <span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> term<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">function</span> <span class="token function">formatList</span><span class="token punctuation">(</span><span class="token parameter">textArray</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> textArray<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^</span><span class="token regex-delimiter">/</span><span class="token regex-flags">gm</span></span><span class="token punctuation">,</span> <span class="token string">' '</span><span class="token punctuation">.</span><span class="token function">repeat</span><span class="token punctuation">(</span>itemIndentWidth<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Usage: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>helper<span class="token punctuation">.</span><span class="token function">commandUsage</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

  <span class="token comment">// 描述符</span>
  <span class="token keyword">const</span> commandDescription <span class="token operator">=</span> helper<span class="token punctuation">.</span><span class="token function">commandDescription</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>commandDescription<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    output <span class="token operator">=</span> output<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span><span class="token punctuation">[</span>commandDescription<span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// 参数</span>
  <span class="token keyword">const</span> argumentList <span class="token operator">=</span> helper<span class="token punctuation">.</span><span class="token function">visibleArguments</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">argument</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token function">formatItem</span><span class="token punctuation">(</span>
      helper<span class="token punctuation">.</span><span class="token function">argumentTerm</span><span class="token punctuation">(</span>argument<span class="token punctuation">)</span><span class="token punctuation">,</span>
      helper<span class="token punctuation">.</span><span class="token function">argumentDescription</span><span class="token punctuation">(</span>argument<span class="token punctuation">)</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>argumentList<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    output <span class="token operator">=</span> output<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'Arguments:'</span><span class="token punctuation">,</span> <span class="token function">formatList</span><span class="token punctuation">(</span>argumentList<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// 选项</span>
  <span class="token keyword">const</span> optionList <span class="token operator">=</span> helper<span class="token punctuation">.</span><span class="token function">visibleOptions</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">option</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token function">formatItem</span><span class="token punctuation">(</span>
      helper<span class="token punctuation">.</span><span class="token function">optionTerm</span><span class="token punctuation">(</span>option<span class="token punctuation">)</span><span class="token punctuation">,</span>
      helper<span class="token punctuation">.</span><span class="token function">optionDescription</span><span class="token punctuation">(</span>option<span class="token punctuation">)</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>optionList<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    output <span class="token operator">=</span> output<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'Options:'</span><span class="token punctuation">,</span> <span class="token function">formatList</span><span class="token punctuation">(</span>optionList<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// 命令</span>
  <span class="token keyword">const</span> commandList <span class="token operator">=</span> helper<span class="token punctuation">.</span><span class="token function">visibleCommands</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">cmd</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token function">formatItem</span><span class="token punctuation">(</span>
      helper<span class="token punctuation">.</span><span class="token function">subcommandTerm</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token punctuation">,</span>
      helper<span class="token punctuation">.</span><span class="token function">subcommandDescription</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>commandList<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    output <span class="token operator">=</span> output<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'Commands:'</span><span class="token punctuation">,</span> <span class="token function">formatList</span><span class="token punctuation">(</span>commandList<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">return</span> output<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> 
  <h4>自定义</h4> 
  <p>使用<code>addHelpText</code>方法添加额外的帮助信息。</p> 
  <pre><code class="prism language-js">program<span class="token punctuation">.</span><span class="token function">addHelpText</span><span class="token punctuation">(</span><span class="token string">'after'</span><span class="token punctuation">,</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">call help</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> 
  <pre><code class="prism language-bash">node index.js -h
Usage: index <span class="token punctuation">[</span>options<span class="token punctuation">]</span>

Options:
  -h, --help  display <span class="token builtin class-name">help</span> <span class="token keyword">for</span> <span class="token builtin class-name">command</span>
call <span class="token builtin class-name">help</span>
</code></pre> 
  <p><code>addHelpText</code>方法的第一个参数是添加的帮助信息展示的位置,<br> 包括如下:</p> 
  <ul> 
   <li> <p><code>beforeAll</code>:作为全局标头栏展示</p> </li> 
   <li> <p><code>before</code>:在内建帮助信息之前展示</p> </li> 
   <li> <p><code>after</code>:在内建帮助信息之后展示</p> </li> 
   <li> <p><code>afterAll</code>:作为全局末尾栏展示</p> </li> 
  </ul> 
  <p><code>源码解析:</code><br> 在执行<code>addHelpText</code>方法后,会对该事件进行监听,同时执行输入帮助命令时会按顺序执行所有事件,从而实现自定义信息的展示。</p> 
  <p><code>addHelpText</code></p> 
  <pre><code class="prism language-js"><span class="token function">addHelpText</span><span class="token punctuation">(</span><span class="token parameter">position<span class="token punctuation">,</span> text</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> allowedValues <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'beforeAll'</span><span class="token punctuation">,</span> <span class="token string">'before'</span><span class="token punctuation">,</span> <span class="token string">'after'</span><span class="token punctuation">,</span> <span class="token string">'afterAll'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
  <span class="token comment">// 过滤</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>allowedValues<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>position<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Unexpected value for position to addHelpText.
Expecting one of '</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>allowedValues<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">"', '"</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">'</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">const</span> helpEvent <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>position<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">Help</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
  <span class="token comment">// 监听事件</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span>helpEvent<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">context</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> helpStr<span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> text <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      helpStr <span class="token operator">=</span> <span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">{</span> error<span class="token operator">:</span> context<span class="token punctuation">.</span>error<span class="token punctuation">,</span> command<span class="token operator">:</span> context<span class="token punctuation">.</span>command <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      helpStr <span class="token operator">=</span> text<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">// Ignore falsy value when nothing to output.</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>helpStr<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      context<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>helpStr<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> 
  <p><code>outputHelp</code></p> 
  <pre><code class="prism language-js"><span class="token function">outputHelp</span><span class="token punctuation">(</span><span class="token parameter">contextOptions</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">let</span> deprecatedCallback<span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> contextOptions <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    deprecatedCallback <span class="token operator">=</span> contextOptions<span class="token punctuation">;</span>
    contextOptions <span class="token operator">=</span> <span class="token keyword">undefined</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">const</span> context <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">_getHelpContext</span><span class="token punctuation">(</span>contextOptions<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// 遍历触发所有祖先命令的 beforeAllHelp 事件</span>
  <span class="token function">getCommandAndParents</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">reverse</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token comment">// 触发 beforeAllHelp</span>
    <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">command</span><span class="token punctuation">)</span> <span class="token operator">=></span> command<span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token string">'beforeAllHelp'</span><span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// 触发 beforeHelp</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token string">'beforeHelp'</span><span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">let</span> helpInformation <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">helpInformation</span><span class="token punctuation">(</span>context<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>deprecatedCallback<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    helpInformation <span class="token operator">=</span> <span class="token function">deprecatedCallback</span><span class="token punctuation">(</span>helpInformation<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>
      <span class="token keyword">typeof</span> helpInformation <span class="token operator">!==</span> <span class="token string">'string'</span> <span class="token operator">&&</span>
      <span class="token operator">!</span>Buffer<span class="token punctuation">.</span><span class="token function">isBuffer</span><span class="token punctuation">(</span>helpInformation<span class="token punctuation">)</span>
    <span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">'outputHelp callback must return a string or a Buffer'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
  context<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>helpInformation<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// 触发 help 指令</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>_helpLongFlag<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// deprecated</span>
  <span class="token comment">// 触发 afterHelp</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token string">'afterHelp'</span><span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// 遍历触发所有祖先命令的 afterAllHelp 事件</span>
  <span class="token function">getCommandAndParents</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">command</span><span class="token punctuation">)</span> <span class="token operator">=></span>
    <span class="token comment">// 触发 afterAllHelp</span>
    command<span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token string">'afterAllHelp'</span><span class="token punctuation">,</span> context<span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> 
  <h4><code>showHelpAfterError</code>展示帮助信息</h4> 
  <pre><code class="prism language-js">program<span class="token punctuation">.</span><span class="token function">showHelpAfterError</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 或者</span>
program<span class="token punctuation">.</span><span class="token function">showHelpAfterError</span><span class="token punctuation">(</span><span class="token string">'(add --help for additional information)'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> 
  <pre><code class="prism language-bash">node index.js -asd
error: unknown option <span class="token string">'-asd'</span>
<span class="token punctuation">(</span>add --help <span class="token keyword">for</span> additional information<span class="token punctuation">)</span>
</code></pre> 
 </div> 
</div>
                            </div>
                        </div>
                    </div>
                    <!--PC和WAP自适应版-->
                    <div id="SOHUCS" sid="1644813476289372160"></div>
                    <script type="text/javascript" src="/views/front/js/chanyan.js"></script>
                    <!-- 文章页-底部 动态广告位 -->
                    <div class="youdao-fixed-ad" id="detail_ad_bottom"></div>
                </div>
                <div class="col-md-3">
                    <div class="row" id="ad">
                        <!-- 文章页-右侧1 动态广告位 -->
                        <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_1"> </div>
                        </div>
                        <!-- 文章页-右侧2 动态广告位 -->
                        <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_2"></div>
                        </div>
                        <!-- 文章页-右侧3 动态广告位 -->
                        <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_3"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="container">
        <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(javascript,js)</h4>
        <div id="paradigm-article-related">
            <div class="recommend-post mb30">
                <ul class="widget-links">
                    <li><a href="/article/1834951677422170112.htm"
                           title="React项目的开发前准备 以及 JSX 的基本使用" target="_blank">React项目的开发前准备 以及 JSX 的基本使用</a>
                        <span class="text-muted">渡鸦七</span>
<a class="tag" taget="_blank" href="/search/React/1.htm">React</a><a class="tag" taget="_blank" href="/search/react.js/1.htm">react.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/1.htm">前端框架</a>
                        <div>React项目的开发前准备以及JSX的基本使用React项目创建create-react-appnpxcreate-react-appmy-appcdmy-appnpmstartyarncreatereact-appyarncreatereact-appmy-appcdmy-appyarnstartcreate-react-app和yarncreatereact-app都可以快速创建一个React</div>
                    </li>
                    <li><a href="/article/1834936812280311808.htm"
                           title="jsp 从后台Map中取值" target="_blank">jsp 从后台Map中取值</a>
                        <span class="text-muted">yank1225</span>
<a class="tag" taget="_blank" href="/search/jsp/1.htm">jsp</a><a class="tag" taget="_blank" href="/search/%E4%BB%8Emap%E5%8F%96%E5%80%BC/1.htm">从map取值</a><a class="tag" taget="_blank" href="/search/jsp/1.htm">jsp</a><a class="tag" taget="_blank" href="/search/%E6%8C%89key%E8%8E%B7%E5%8F%96map%E4%B8%AD%E7%9A%84%E5%AF%B9%E5%BA%94%E5%80%BC/1.htm">按key获取map中的对应值</a><a class="tag" taget="_blank" href="/search/springmMVC/1.htm">springmMVC</a><a class="tag" taget="_blank" href="/search/jsp%E9%A1%B5%E9%9D%A2%E5%8F%96%E5%BE%97map%E5%80%BC/1.htm">jsp页面取得map值</a>
                        <div>在jsp页面有的时候需要从后台传过来的Map中取特定值,并显示在页面上,网上有很多说怎么取值的,但是找了好久很多都是讲的怎么循环取值,如果你需要在table中显示值那该怎么办呢?很多都没有讲,我把我的方法简单介绍下。场景是这样的下面是table的行数据从后台controller返回分页信息,pageInfo.list是当前行数据,item.houseType是数据,但是这个是值(1或者2等等)并不</div>
                    </li>
                    <li><a href="/article/1834933410066427904.htm"
                           title="Protobuf3语言指南" target="_blank">Protobuf3语言指南</a>
                        <span class="text-muted">R-QWERT</span>
<a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%8C%96%E4%B8%8E%E5%BA%8F%E5%88%97%E5%8C%96/1.htm">数据结构化与序列化</a><a class="tag" taget="_blank" href="/search/protobuf/1.htm">protobuf</a>
                        <div>定义一个消息类型指定字段类型分配标识号指定字段规则添加更多消息类型添加注释保留标识符(Reserved)从.proto文件生成了什么?标量数值类型默认值枚举使用其他消息类型导入定义使用proto2消息类型嵌套类型更新一个消息类型AnyOneof使用OneofOneof特性向后兼容性问题映射(Maps)向后兼容性问题包(Packages)包及名称的解析定义服务JSON映射选项自定义选项生成你的类英文</div>
                    </li>
                    <li><a href="/article/1834926344224468992.htm"
                           title="uniapp H5 关掉全部头部header" target="_blank">uniapp H5 关掉全部头部header</a>
                        <span class="text-muted">qq_39016177</span>
<a class="tag" taget="_blank" href="/search/uni-app/1.htm">uni-app</a>
                        <div>uniappH5关掉全部头部header1.进入pages.json文件"globalStyle":{//"navigationStyle":"custom","navigationBarTextStyle":"black","navigationBarTitleText":"","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":</div>
                    </li>
                    <li><a href="/article/1834926216486940672.htm"
                           title="JS 获取数组对象中某个属性的最大值或最小值" target="_blank">JS 获取数组对象中某个属性的最大值或最小值</a>
                        <span class="text-muted">qq_36437172</span>
<a class="tag" taget="_blank" href="/search/JS/1.htm">JS</a><a class="tag" taget="_blank" href="/search/Math.max/1.htm">Math.max</a><a class="tag" taget="_blank" href="/search/Math.min/1.htm">Math.min</a><a class="tag" taget="_blank" href="/search/sort/1.htm">sort</a><a class="tag" taget="_blank" href="/search/apply/1.htm">apply</a>
                        <div>最近的开发中经常会遇到前端自己生成唯一id,然后在数组中增加删除插入对象,这样一来就要的要当前使用的id的最大值。总结一下,有两种比较简便的方法可以做到:1.将属性值通过map生成一个数组,再使用Math.max取最大值2.使用排序sort,先对数组的项排序,再取排序后的对应的项的值数组对象如下,求id的最大值和最小值list=[{id:1,name:'jack'},    {id:2,name:</div>
                    </li>
                    <li><a href="/article/1834926217485185024.htm"
                           title="vue 生成PDF(A4标准PDF分页)" target="_blank">vue 生成PDF(A4标准PDF分页)</a>
                        <span class="text-muted">qq_39016177</span>
<a class="tag" taget="_blank" href="/search/HTML2Canvas/1.htm">HTML2Canvas</a><a class="tag" taget="_blank" href="/search/jsPDF/1.htm">jsPDF</a><a class="tag" taget="_blank" href="/search/%E5%AF%BC%E5%87%BA/1.htm">导出</a><a class="tag" taget="_blank" href="/search/PDF%E8%BD%AC%E6%8D%A2/1.htm">PDF转换</a><a class="tag" taget="_blank" href="/search/DOM%E6%93%8D%E4%BD%9C/1.htm">DOM操作</a>
                        <div>1.先安装两个插件//页面转图片npminstall--savehtml2canvas//图片转PDFnpminstalljspdf--save 2.在需要导出的dom节点增加ref='pdf'例如  这是待转换的页面,点击导出点击导出PDF3.定义导出方法handleExport(){   downloadPDF(this.$refs.pdf);},4.在页面导入 import{download</div>
                    </li>
                    <li><a href="/article/1834925082288418816.htm"
                           title="四、webpack4.0 - tapable" target="_blank">四、webpack4.0 - tapable</a>
                        <span class="text-muted">Razas</span>
<a class="tag" taget="_blank" href="/search/WEBPACK4/1.htm">WEBPACK4</a><a class="tag" taget="_blank" href="/search/webpack4.0/1.htm">webpack4.0</a>
                        <div>一、tapable介绍webpack中插件的时候,需要用到tapable。新建一个项目WEBPACK-Tapable。初始化package.json:npminit-y安装:npminstalltapable--savetapable是一个包。二、tapable三、AsyncParralleHook四、AsyncSeriesHook五、AsyncSeriesWaterfall</div>
                    </li>
                    <li><a href="/article/1834924576757346304.htm"
                           title="Json格式化" target="_blank">Json格式化</a>
                        <span class="text-muted">微赚淘客系统@聚娃科技</span>
<a class="tag" taget="_blank" href="/search/json/1.htm">json</a>
                        <div>Json格式化大家好,我是微赚淘客机器人的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!Json格式化:让数据更亮眼,解密Json的奇妙世界在现代Web开发中,Json(JavaScriptObjectNotation)已经成为数据交换的标准之一。然而,对于人眼来说,一串紧凑的Json字符串并不直观,而经过格式化处理后的Json却如同一幅清晰的画面。本文将深入探讨Json格式化的重要性、实现方法以</div>
                    </li>
                    <li><a href="/article/1834924072354541568.htm"
                           title="PostgreSQL进阶教程" target="_blank">PostgreSQL进阶教程</a>
                        <span class="text-muted">爱分享的码瑞哥</span>
<a class="tag" taget="_blank" href="/search/postgresql/1.htm">postgresql</a>
                        <div>PostgreSQL进阶教程目录事务和并发控制事务事务隔离级别锁高级查询联合查询窗口函数子查询CTE(公用表表达式)数据类型自定义数据类型数组JSON高级索引部分索引表达式索引GIN和GiST索引性能调优查询优化配置优化备份与恢复物理备份逻辑备份扩展与插件PostGISpg_cron集群与高可用StreamingReplicationPatroni事务和并发控制事务事务是一个或多个SQL语句的组合</div>
                    </li>
                    <li><a href="/article/1834920164567642112.htm"
                           title="前端同学必备:教你如何安装、使用Chrome的vue-devtools插件" target="_blank">前端同学必备:教你如何安装、使用Chrome的vue-devtools插件</a>
                        <span class="text-muted">界忆</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E7%BC%96%E7%A8%8B/1.htm">前端编程</a><a class="tag" taget="_blank" href="/search/Vue-devtools%E6%8F%92%E4%BB%B6/1.htm">Vue-devtools插件</a><a class="tag" taget="_blank" href="/search/chrome/1.htm">chrome</a><a class="tag" taget="_blank" href="/search/devtools/1.htm">devtools</a>
                        <div>I.介绍vue-devtools插件Vue-devtools是一个Chrome浏览器插件,它是一个浏览器调试工具,用于开发Vue.js应用程序。它可以用于Vue.js应用程序的调试,可以更好地了解应用程序的结构和状态,以及帮助快速修复代码错误。Vue-devtools插件的作用和优势如下:1.调试Vue.js应用程序:Vue-devtools是一个强大的调试工具,可以帮助开发人员正确地调试应用程序</div>
                    </li>
                    <li><a href="/article/1834919912410279936.htm"
                           title="Tapable" target="_blank">Tapable</a>
                        <span class="text-muted">信海利世</span>
<a class="tag" taget="_blank" href="/search/webpack/1.htm">webpack</a><a class="tag" taget="_blank" href="/search/webpack/1.htm">webpack</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>一、Tapable是什么?Tapable是一个类似于Node.js的EventEmitter的库,主要是控制钩子函数的发布与订阅,控制着webpack的插件系统。Tapable库暴露了很多Hook(钩子)类,为插件提供挂载的钩子const{SyncHook,//同步钩子SyncBailHook,//同步熔断钩子即return一个非undefined的值,则不再继续执行后面的监听函数SyncWate</div>
                    </li>
                    <li><a href="/article/1834919786136563712.htm"
                           title="基于nodejs+vue的美妆彩妆网站的设计与实现(源码+LW+调试文档+讲解等)" target="_blank">基于nodejs+vue的美妆彩妆网站的设计与实现(源码+LW+调试文档+讲解等)</a>
                        <span class="text-muted">程序员gelei</span>
<a class="tag" taget="_blank" href="/search/nodejs%E6%AF%95%E4%B8%9A%E8%AE%BE%E8%AE%A1%E9%A1%B9%E7%9B%AE/1.htm">nodejs毕业设计项目</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a>
                        <div>目录:博主介绍:完整视频演示:系统技术介绍:后端Java介绍前端框架Vue介绍具体功能截图:部分代码参考:Mysql表设计参考:项目测试:项目论文:为什么选择我:源码获取:博主介绍:博主:程序员gelei:全网拥有20W+粉丝、CSDN作者、博客专家、全栈领域优质创作者、平台优质Java创作者、专注于Java、小程序、python、安卓技术领域和毕业项目实战✌Java精品实战案例《1000套》20</div>
                    </li>
                    <li><a href="/article/1834915502644883456.htm"
                           title="【保姆级】使用Java注解和反射实现JSON字段自动重命名" target="_blank">【保姆级】使用Java注解和反射实现JSON字段自动重命名</a>
                        <span class="text-muted">AQin1012</span>
<a class="tag" taget="_blank" href="/search/Java/1.htm">Java</a><a class="tag" taget="_blank" href="/search/%E5%87%BA%E5%9D%91%E5%BF%85%E5%A4%87%7E/1.htm">出坑必备~</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E6%B3%A8%E8%A7%A3/1.htm">注解</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>不知道有没有同学遇到过对接业务方代码非常“独具一格”(不符合通用规范且不愿意配合修改emmmm。。。),于是就只能“被迫”按他的格式来,但是又不想因为他的不规范导致我们自己创建的接收对象也非常的“一言难尽”。。。今天这篇帮你解决这个问题~(老规矩:附完整可执行代码)先给初学Java的同学补下基础,涉及到一些实现这个功能需要的知识点(了解的朋友可以直接跳过~)Java注解(Annotation)Ja</div>
                    </li>
                    <li><a href="/article/1834913862382612480.htm"
                           title="qiankun 结合 vue3, 小白快速上手体验" target="_blank">qiankun 结合 vue3, 小白快速上手体验</a>
                        <span class="text-muted">陈y_d</span>
<a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a>
                        <div>一、主应用改造首先需要维护一份微应用列表,里面包含了微应用的名称、入口和生效规则,若需要给子应用传递内容,可以在props传入对应的内容//app.jsconstapps=[{name:'micro-vue-app3',entry:'//localhost:3013',container:'#micro-vue-app3',activeRule:'/micro-vue3-app3',props:{</div>
                    </li>
                    <li><a href="/article/1834905295411834880.htm"
                           title="H5新增标签和属性" target="_blank">H5新增标签和属性</a>
                        <span class="text-muted">yx_back</span>
<a class="tag" taget="_blank" href="/search/Html/1.htm">Html</a><a class="tag" taget="_blank" href="/search/H5%E6%96%B0%E5%A2%9E%E5%B1%9E%E6%80%A7/1.htm">H5新增属性</a><a class="tag" taget="_blank" href="/search/H5%E6%96%B0%E5%A2%9E%E6%A0%87%E7%AD%BE/1.htm">H5新增标签</a>
                        <div>H5新增标签和属性H5新增标签1、结构标签2、媒体标签3、表单标签4、其他功能标签H5新增属性1、对于js进行添加的属性。2、网页中标签中加入小图标的样式代码3、iframe新增属性4、其他属性H5全局属性可直接在标签里插入的:data-自定义属性名字;H5新增标签1、结构标签header:某个区块的头部信息/标题;section:独立内容区块,可以用h1~h6组成大纲,表示文档结构,也可以有章节</div>
                    </li>
                    <li><a href="/article/1834905169196838912.htm"
                           title="uniapp+uview-plus实现微信小程序自定义tabbar" target="_blank">uniapp+uview-plus实现微信小程序自定义tabbar</a>
                        <span class="text-muted">yx_back</span>
<a class="tag" taget="_blank" href="/search/%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">小程序</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/uniapp/1.htm">uniapp</a><a class="tag" taget="_blank" href="/search/uni-app/1.htm">uni-app</a><a class="tag" taget="_blank" href="/search/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">微信小程序</a><a class="tag" taget="_blank" href="/search/uview-plus/1.htm">uview-plus</a>
                        <div>参考文档微信小程序相关开发文档链接:https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html虽然是uniapp框架但是实现方式和原生小程序相似实现思路1、app.json里面tabBar添加配置custom:true,其他和非自定义设置一样2、在components文件夹里添加Tabb</div>
                    </li>
                    <li><a href="/article/1834902397802082304.htm"
                           title="记录:在ubuntu中以C语言实现json文件读取遇到的问题(1)(说不定会有2)" target="_blank">记录:在ubuntu中以C语言实现json文件读取遇到的问题(1)(说不定会有2)</a>
                        <span class="text-muted">fighting_dou</span>
<a class="tag" taget="_blank" href="/search/ubuntu/1.htm">ubuntu</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a>
                        <div>[4.12]记录在ubuntu中以C语言实现json文件读取遇到的问题(1)(说不定会有2)(暂记录遇到的问题及解决,其中还有些原因没有搞明白)1.首先过程参考自一位大佬的博文(目前找到的c语言解析json文件很详细的博文了,感谢博主!):https://blog.csdn.net/qq_35522096/article/details/115358647?utm_medium=distribut</div>
                    </li>
                    <li><a href="/article/1834900635116466176.htm"
                           title="Ubuntu虚拟机在node命令行中编译.sol文件报错:{“errors“:[{“component“:“general“,“formattedMessage“...(已解决)" target="_blank">Ubuntu虚拟机在node命令行中编译.sol文件报错:{“errors“:[{“component“:“general“,“formattedMessage“...(已解决)</a>
                        <span class="text-muted">拔牙不打麻药</span>
<a class="tag" taget="_blank" href="/search/%E7%96%91%E9%9A%BE%E6%9D%82%E7%97%87/1.htm">疑难杂症</a><a class="tag" taget="_blank" href="/search/%E5%8C%BA%E5%9D%97%E9%93%BE/1.htm">区块链</a><a class="tag" taget="_blank" href="/search/%E8%99%9A%E6%8B%9F%E6%9C%BA/1.htm">虚拟机</a><a class="tag" taget="_blank" href="/search/node/1.htm">node</a>
                        <div>Ubuntu虚拟机在node命令行下编译.sol文件报错'{"errors":[{"component":"general","formattedMessage":"*Line1,Column1\\nSyntaxerror:value,objectorarrayexpected.\\n*Line1,Column2\\nExtranon-whitespaceafterJSONvalue.\\n","</div>
                    </li>
                    <li><a href="/article/1834899627153911808.htm"
                           title="python中读取文件报错_python中读取json文件报错,TypeError:the Json object must be str, bytes or bytearray,not ‘TextI..." target="_blank">python中读取文件报错_python中读取json文件报错,TypeError:the Json object must be str, bytes or bytearray,not ‘TextI...</a>
                        <span class="text-muted">weixin_39783915</span>
<a class="tag" taget="_blank" href="/search/python%E4%B8%AD%E8%AF%BB%E5%8F%96%E6%96%87%E4%BB%B6%E6%8A%A5%E9%94%99/1.htm">python中读取文件报错</a>
                        <div>利用python中的json读取json文件时,因为错误使用了相应的方法导致报错:TypeError:theJsonobjectmustbestr,bytesorbytearray,not‘TextIOWrapper’。解决方法:首先要弄明白json有四个方法:dumps和loads、dump和load。其中,dumps和loads是在内存中转换(python对象和json字符串之间的转换),而d</div>
                    </li>
                    <li><a href="/article/1834898490354921472.htm"
                           title="linux json编译报错" target="_blank">linux json编译报错</a>
                        <span class="text-muted">nancynull</span>
<a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/Linux/1.htm">Linux</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E8%AF%91/1.htm">编译</a>
                        <div>背景:ubuntu16.04,使用apt-get安装过jsoncpp问题一:编译时报找不到json.h问题二:编译.so时,提示/usr/bin/ld:cannotfind-ljson解决方案:https://stackoverflow.com/questions/36861355/fatal-error-with-jsoncpp-while-compiling具体翻译如下:针对问题一:修改#in</div>
                    </li>
                    <li><a href="/article/1834897986417684480.htm"
                           title="webpack怎么配置单页面或者多页面项目?" target="_blank">webpack怎么配置单页面或者多页面项目?</a>
                        <span class="text-muted">镜中的女孩-potato</span>
<a class="tag" taget="_blank" href="/search/webpack/1.htm">webpack</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a>
                        <div>单页直接在entry中指定单页面的入口文件即可,对于多页面来说,如果页面之间有依赖关系可以考虑将entry的值改成一个数组,数组中的每一项是入口文件的地址,并且通过dependOn配置多个入口的依赖关系,一般的,我们也可以直接在entry中配置多个入口文件的键值对1、单页面举个例子=>你有这样一个项目架构├──config│├──webpack.config.js//webpack配置文件├──s</div>
                    </li>
                    <li><a href="/article/1834893444712067072.htm"
                           title="ubuntu16 jsoncpp1.9编译及使用" target="_blank">ubuntu16 jsoncpp1.9编译及使用</a>
                        <span class="text-muted">noscallion</span>
<a class="tag" taget="_blank" href="/search/ubuntu/1.htm">ubuntu</a><a class="tag" taget="_blank" href="/search/json/1.htm">json</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a>
                        <div>文章目录前言1.下载jsoncpp2.解压并安装3.编译4.使用(1)创建项目文件夹,编写main.cpp文件。如下:(2)新建一个config.json的json文件:(3)创建CMakeLists.txt文件,内容如下:(4)新建build文件夹后记前言网上现有教程存在各种问题,比如jsoncpp是很老的版本。直接运行高版本安装包中提供的python脚本,在使用时会导致链接库等问题。使用CMa</div>
                    </li>
                    <li><a href="/article/1834891931621093376.htm"
                           title="uniapp 获取当前位置和地理信息(微信小程序和APP)" target="_blank">uniapp 获取当前位置和地理信息(微信小程序和APP)</a>
                        <span class="text-muted">火星代码</span>
<a class="tag" taget="_blank" href="/search/uni-app/1.htm">uni-app</a><a class="tag" taget="_blank" href="/search/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">微信小程序</a><a class="tag" taget="_blank" href="/search/%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">小程序</a>
                        <div>一、在微信小程序中获取位置信息1、首先引入amap-wx.130.js文件,在项目中可以新建文件夹common,在下面引入该js文件2、在使用的页面引入该js,importamapfrom'@/common/amap-wx.130.js'exportdefault{data(){return{amapPlugin:null}}}3、获取定位信息(注意先需要申请高德地图的key)申请方式如下连接vu</div>
                    </li>
                    <li><a href="/article/1834889286948843520.htm"
                           title="fetch-event-source 如何通过script全局引入" target="_blank">fetch-event-source 如何通过script全局引入</a>
                        <span class="text-muted">cuiyuchen111</span>
<a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>fetchEventSource源码中导出了两种类型的包cjs和esm。但是有个需求如何在原生是js中通过script标签引呢?需要加上type=module。今天介绍另一种方法下载源码文件:https://github.com/Azure/fetch-event-source.git安装:npminstall--save-devwebpackwebpack-clits-loadertypescr</div>
                    </li>
                    <li><a href="/article/1834883992420184064.htm"
                           title="【Webpack 踩坑】CSS加载缓慢" target="_blank">【Webpack 踩坑】CSS加载缓慢</a>
                        <span class="text-muted">①条咸鱼</span>
<a class="tag" taget="_blank" href="/search/webpack/1.htm">webpack</a><a class="tag" taget="_blank" href="/search/css/1.htm">css</a><a class="tag" taget="_blank" href="/search/rust/1.htm">rust</a>
                        <div>问题:使用webpack5,单独index.scss在assets/css目录下,但是不管是production还是development环境下,都会出现dom加载完后再渲染样式本意是想要将样式单独打包到一个文件夹,还有压缩css于是用了mini-css-extract-plugin这个loader(前提要先安装)//webpack.config.jsconstMiniCssExtractPlug</div>
                    </li>
                    <li><a href="/article/1834880085786718208.htm"
                           title="python毕业设计作品:python闲置物品二手交易平台系统设计与实现毕业设计源代码(Django框架)" target="_blank">python毕业设计作品:python闲置物品二手交易平台系统设计与实现毕业设计源代码(Django框架)</a>
                        <span class="text-muted">黄菊华老师</span>
<a class="tag" taget="_blank" href="/search/%E6%AF%95%E8%AE%BE%E8%B5%84%E6%96%99/1.htm">毕设资料</a><a class="tag" taget="_blank" href="/search/python%E4%BA%8C%E6%89%8B%E4%BA%A4%E6%98%93%E5%B9%B3%E5%8F%B0%E7%B3%BB%E7%BB%9F/1.htm">python二手交易平台系统</a>
                        <div>博主介绍:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩。项目配有对应开发文档、开题报告、任务书、PPT、论文模版等项目都录了发布和功能操作演示视频;项目的界面和功能都可以定制,包安装运行!!!如果需要联系我,可以在CSD</div>
                    </li>
                    <li><a href="/article/1834877734849966080.htm"
                           title="JS 获取时间" target="_blank">JS 获取时间</a>
                        <span class="text-muted">买买买买菜</span>

                        <div>/**针对Ext的工具类*/exportvarMrYangUtil=function(){/****获得当前时间*/this.getCurrentDate=function(){returnnewDate();};/****获得本周起止时间*/this.getCurrentWeek=function(){//起止日期数组varstartStop=newArray();//获取当前时间varcurr</div>
                    </li>
                    <li><a href="/article/1834871132679925760.htm"
                           title="js数组方法map和filter" target="_blank">js数组方法map和filter</a>
                        <span class="text-muted">人间废料记</span>
<a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>目录.map()方法概念语法注意使用场景.filter()方法概念语法注意使用场景.map()和.filter()的区别和联系.map()方法概念.map()函数是JavaScript数组结构中很实用的一个方法之一。可以将map()方法视为经过一个循环并在回调函数中编写语句(格式化、数据处理)以构造一个新数组。用来创建新数组、修改其内容并保持原始数组不变的通用方法。当出现需要修改现有数组的内容并将</div>
                    </li>
                    <li><a href="/article/1834868968570056704.htm"
                           title="javascript - 模拟 for-in 循环" target="_blank">javascript - 模拟 for-in 循环</a>
                        <span class="text-muted">廖马儿</span>

                        <div>获取:"key,value"在for循环中。varlist={'aaa':'111','bbb':'222','ccc':'333'};我知道可以用forin语句获取键值对的值如下for(varkeyinlist){key;//输出aaabbbccclist[key]//输出为111222333}</div>
                    </li>
                    <li><a href="/article/1834862560977973248.htm"
                           title="vue axios 如何读取项目下的json文件" target="_blank">vue axios 如何读取项目下的json文件</a>
                        <span class="text-muted">战族狼魂</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/json/1.htm">json</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a>
                        <div>在Vue项目中,使用axios读取本地的JSON文件可以通过将JSON文件放置在public目录中,然后通过axios发起请求读取。步骤:将JSON文件放置在public目录下:Vue项目中的public目录是静态资源目录,项目编译后这些文件可以通过URL直接访问。将你的JSON文件,比如data.json,放在public目录中。使用axios读取JSON文件:在你的Vue组件中,通过axios</div>
                    </li>
                                <li><a href="/article/18.htm"
                                       title="jQuery 跨域访问的三种方式 No 'Access-Control-Allow-Origin' header is present on the reque" target="_blank">jQuery 跨域访问的三种方式 No 'Access-Control-Allow-Origin' header is present on the reque</a>
                                    <span class="text-muted">qiaolevip</span>
<a class="tag" taget="_blank" href="/search/%E6%AF%8F%E5%A4%A9%E8%BF%9B%E6%AD%A5%E4%B8%80%E7%82%B9%E7%82%B9/1.htm">每天进步一点点</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E6%B0%B8%E6%97%A0%E6%AD%A2%E5%A2%83/1.htm">学习永无止境</a><a class="tag" taget="_blank" href="/search/%E8%B7%A8%E5%9F%9F/1.htm">跨域</a><a class="tag" taget="_blank" href="/search/%E4%BC%97%E8%A7%82%E5%8D%83%E8%B1%A1/1.htm">众观千象</a>
                                    <div>XMLHttpRequest cannot load http://v.xxx.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access. test.html:1
</div>
                                </li>
                                <li><a href="/article/145.htm"
                                       title="mysql 分区查询优化" target="_blank">mysql 分区查询优化</a>
                                    <span class="text-muted">annan211</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E5%8C%BA/1.htm">分区</a><a class="tag" taget="_blank" href="/search/%E4%BC%98%E5%8C%96/1.htm">优化</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a>
                                    <div>


分区查询优化

  引入分区可以给查询带来一定的优势,但同时也会引入一些bug.
  
  分区最大的优点就是优化器可以根据分区函数来过滤掉一些分区,通过分区过滤可以让查询扫描更少的数据。
  所以,对于访问分区表来说,很重要的一点是要在where 条件中带入分区,让优化器过滤掉无需访问的分区。
  
  可以通过查看explain执行计划,是否携带 partitions</div>
                                </li>
                                <li><a href="/article/272.htm"
                                       title="MYSQL存储过程中使用游标" target="_blank">MYSQL存储过程中使用游标</a>
                                    <span class="text-muted">chicony</span>
<a class="tag" taget="_blank" href="/search/Mysql%E5%AD%98%E5%82%A8%E8%BF%87%E7%A8%8B/1.htm">Mysql存储过程</a>
                                    <div>DELIMITER $$ 
DROP PROCEDURE IF EXISTS getUserInfo $$ 
CREATE PROCEDURE getUserInfo(in date_day datetime)-- -- 实例-- 存储过程名为:getUserInfo-- 参数为:date_day日期格式:2008-03-08--    BEGINdecla</div>
                                </li>
                                <li><a href="/article/399.htm"
                                       title="mysql 和 sqlite 区别" target="_blank">mysql 和 sqlite 区别</a>
                                    <span class="text-muted">Array_06</span>
<a class="tag" taget="_blank" href="/search/sqlite/1.htm">sqlite</a>
                                    <div>转载: 
http://www.cnblogs.com/ygm900/p/3460663.html 
 
mysql 和 sqlite 区别 
 
SQLITE是单机数据库。功能简约,小型化,追求最大磁盘效率 
MYSQL是完善的服务器数据库。功能全面,综合化,追求最大并发效率 
 
MYSQL、Sybase、Oracle等这些都是试用于服务器数据量大功能多需要安装,例如网站访问量比较大的。而sq</div>
                                </li>
                                <li><a href="/article/526.htm"
                                       title="pinyin4j使用" target="_blank">pinyin4j使用</a>
                                    <span class="text-muted">oloz</span>
<a class="tag" taget="_blank" href="/search/pinyin4j/1.htm">pinyin4j</a>
                                    <div>首先需要pinyin4j的jar包支持;jar包已上传至附件内 
 
方法一:把汉字转换为拼音;例如:编程转换后则为biancheng 
     
 
/**
     * 将汉字转换为全拼
     * @param src 你的需要转换的汉字
     * @param isUPPERCASE 是否转换为大写的拼音; true:转换为大写;fal</div>
                                </li>
                                <li><a href="/article/653.htm"
                                       title="微博发送私信" target="_blank">微博发送私信</a>
                                    <span class="text-muted">随意而生</span>
<a class="tag" taget="_blank" href="/search/%E5%BE%AE%E5%8D%9A/1.htm">微博</a>
                                    <div>在前面文章中说了如和获取登陆时候所需要的cookie,现在只要拿到最后登陆所需要的cookie,然后抓包分析一下微博私信发送界面 
http://weibo.com/message/history?uid=****&name=**** 
可以发现其发送提交的Post请求和其中的数据, 
让后用程序模拟发送POST请求中的数据,带着cookie发送到私信的接入口,就可以实现发私信的功能了。 </div>
                                </li>
                                <li><a href="/article/780.htm"
                                       title="jsp" target="_blank">jsp</a>
                                    <span class="text-muted">香水浓</span>
<a class="tag" taget="_blank" href="/search/jsp/1.htm">jsp</a>
                                    <div>JSP初始化 
    容器载入JSP文件后,它会在为请求提供任何服务前调用jspInit()方法。如果您需要执行自定义的JSP初始化任务,复写jspInit()方法就行了 
 
 
JSP执行 
    这一阶段描述了JSP生命周期中一切与请求相关的交互行为,直到被销毁。 
    当JSP网页完成初始化后</div>
                                </li>
                                <li><a href="/article/907.htm"
                                       title="在 Windows 上安装 SVN Subversion 服务端" target="_blank">在 Windows 上安装 SVN Subversion 服务端</a>
                                    <span class="text-muted">AdyZhang</span>
<a class="tag" taget="_blank" href="/search/SVN/1.htm">SVN</a>
                                    <div>在 Windows 上安装 SVN Subversion 服务端2009-09-16高宏伟哈尔滨市道里区通达街291号 
  
最佳阅读效果请访问原地址:http://blog.donews.com/dukejoe/archive/2009/09/16/1560917.aspx 
  
现在的Subversion已经足够稳定,而且已经进入了它的黄金时段。我们看到大量的项目都在使</div>
                                </li>
                                <li><a href="/article/1034.htm"
                                       title="android开发中如何使用 alertDialog从listView中删除数据?" target="_blank">android开发中如何使用 alertDialog从listView中删除数据?</a>
                                    <span class="text-muted">aijuans</span>
<a class="tag" taget="_blank" href="/search/android/1.htm">android</a>
                                    <div>我现在使用listView展示了很多的配置信息,我现在想在点击其中一条的时候填出 alertDialog,点击确认后就删除该条数据,( ArrayAdapter ,ArrayList,listView 全部删除),我知道在 下面的onItemLongClick 方法中 参数 arg2  是选中的序号,但是我不知道如何继续处理下去        1   2   3   </div>
                                </li>
                                <li><a href="/article/1161.htm"
                                       title="jdk-6u26-linux-x64.bin 安装" target="_blank">jdk-6u26-linux-x64.bin 安装</a>
                                    <span class="text-muted">baalwolf</span>
<a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a>
                                    <div>1.上传安装文件(jdk-6u26-linux-x64.bin) 
2.修改权限 
[root@localhost ~]# ls -l /usr/local/jdk-6u26-linux-x64.bin 
3.执行安装文件 
[root@localhost ~]# cd /usr/local 
[root@localhost local]# ./jdk-6u26-linux-x64.bin&nbs</div>
                                </li>
                                <li><a href="/article/1288.htm"
                                       title="MongoDB经典面试题集锦" target="_blank">MongoDB经典面试题集锦</a>
                                    <span class="text-muted">BigBird2012</span>
<a class="tag" taget="_blank" href="/search/mongodb/1.htm">mongodb</a>
                                    <div>1.什么是NoSQL数据库?NoSQL和RDBMS有什么区别?在哪些情况下使用和不使用NoSQL数据库? 
NoSQL是非关系型数据库,NoSQL = Not Only SQL。 
关系型数据库采用的结构化的数据,NoSQL采用的是键值对的方式存储数据。 
在处理非结构化/半结构化的大数据时;在水平方向上进行扩展时;随时应对动态增加的数据项时可以优先考虑使用NoSQL数据库。 
在考虑数据库的成熟</div>
                                </li>
                                <li><a href="/article/1415.htm"
                                       title="JavaScript异步编程Promise模式的6个特性" target="_blank">JavaScript异步编程Promise模式的6个特性</a>
                                    <span class="text-muted">bijian1013</span>
<a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/Promise/1.htm">Promise</a>
                                    <div>        Promise是一个非常有价值的构造器,能够帮助你避免使用镶套匿名方法,而使用更具有可读性的方式组装异步代码。这里我们将介绍6个最简单的特性。 
        在我们开始正式介绍之前,我们想看看Javascript Promise的样子: 
var p = new Promise(function(r</div>
                                </li>
                                <li><a href="/article/1542.htm"
                                       title="[Zookeeper学习笔记之八]Zookeeper源代码分析之Zookeeper.ZKWatchManager" target="_blank">[Zookeeper学习笔记之八]Zookeeper源代码分析之Zookeeper.ZKWatchManager</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/zookeeper/1.htm">zookeeper</a>
                                    <div>ClientWatchManager接口 
//接口的唯一方法materialize用于确定那些Watcher需要被通知
//确定Watcher需要三方面的因素1.事件状态 2.事件类型 3.znode的path
public interface ClientWatchManager {
    /**
     * Return a set of watchers that should</div>
                                </li>
                                <li><a href="/article/1669.htm"
                                       title="【Scala十五】Scala核心九:隐式转换之二" target="_blank">【Scala十五】Scala核心九:隐式转换之二</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/scala/1.htm">scala</a>
                                    <div>隐式转换存在的必要性, 
  
在Java Swing中,按钮点击事件的处理,转换为Scala的的写法如下: 
  
val button = new JButton
button.addActionListener(
    new ActionListener {
        def actionPerformed(event: ActionEvent) {
 </div>
                                </li>
                                <li><a href="/article/1796.htm"
                                       title="Android JSON数据的解析与封装小Demo" target="_blank">Android JSON数据的解析与封装小Demo</a>
                                    <span class="text-muted">ronin47</span>

                                    <div>转自:http://www.open-open.com/lib/view/open1420529336406.html 
package com.example.jsondemo; 
import org.json.JSONArray; 
import org.json.JSONException; 
import org.json.JSONObject; 
   
impor</div>
                                </li>
                                <li><a href="/article/1923.htm"
                                       title="[设计]字体创意设计方法谈" target="_blank">[设计]字体创意设计方法谈</a>
                                    <span class="text-muted">brotherlamp</span>
<a class="tag" taget="_blank" href="/search/UI/1.htm">UI</a><a class="tag" taget="_blank" href="/search/ui%E8%87%AA%E5%AD%A6/1.htm">ui自学</a><a class="tag" taget="_blank" href="/search/ui%E8%A7%86%E9%A2%91/1.htm">ui视频</a><a class="tag" taget="_blank" href="/search/ui%E6%95%99%E7%A8%8B/1.htm">ui教程</a><a class="tag" taget="_blank" href="/search/ui%E8%B5%84%E6%96%99/1.htm">ui资料</a>
                                    <div>  
从古至今,文字在我们的生活中是必不可少的事物,我们不能想象没有文字的世界将会是怎样。在平面设计中,UI设计师在文字上所花的心思和功夫最多,因为文字能直观地表达UI设计师所的意念。在文字上的创造设计,直接反映出平面作品的主题。 
如设计一幅戴尔笔记本电脑的广告海报,假设海报上没有出现“戴尔”两个文字,即使放上所有戴尔笔记本电脑的图片都不能让人们得知这些电脑是什么品牌。只要写上“戴尔笔</div>
                                </li>
                                <li><a href="/article/2050.htm"
                                       title="单调队列-用一个长度为k的窗在整数数列上移动,求窗里面所包含的数的最大值" target="_blank">单调队列-用一个长度为k的窗在整数数列上移动,求窗里面所包含的数的最大值</a>
                                    <span class="text-muted">bylijinnan</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95%E9%A2%98/1.htm">面试题</a>
                                    <div>import java.util.LinkedList;

/*

单调队列 滑动窗口
单调队列是这样的一个队列:队列里面的元素是有序的,是递增或者递减

题目:给定一个长度为N的整数数列a(i),i=0,1,...,N-1和窗长度k.

要求:f(i) = max{a(i-k+1),a(i-k+2),..., a(i)},i = 0,1,...,N-1

问题的另一种描述就</div>
                                </li>
                                <li><a href="/article/2177.htm"
                                       title="struts2处理一个form多个submit" target="_blank">struts2处理一个form多个submit</a>
                                    <span class="text-muted">chiangfai</span>
<a class="tag" taget="_blank" href="/search/struts2/1.htm">struts2</a>
                                    <div>web应用中,为完成不同工作,一个jsp的form标签可能有多个submit。如下代码: 
<s:form action="submit" method="post" namespace="/my">
<s:textfield name="msg" label="叙述:"></div>
                                </li>
                                <li><a href="/article/2304.htm"
                                       title="shell查找上个月,陷阱及野路子" target="_blank">shell查找上个月,陷阱及野路子</a>
                                    <span class="text-muted">chenchao051</span>
<a class="tag" taget="_blank" href="/search/shell/1.htm">shell</a>
                                    <div>date -d "-1 month" +%F 
    以上这段代码,假如在2012/10/31执行,结果并不会出现你预计的9月份,而是会出现八月份,原因是10月份有31天,9月份30天,所以-1 month在10月份看来要减去31天,所以直接到了8月31日这天,这不靠谱。 
    野路子解决:假设当天日期大于15号</div>
                                </li>
                                <li><a href="/article/2431.htm"
                                       title="mysql导出数据中文乱码问题" target="_blank">mysql导出数据中文乱码问题</a>
                                    <span class="text-muted">daizj</span>
<a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81/1.htm">中文乱码</a><a class="tag" taget="_blank" href="/search/%E5%AF%BC%E6%95%B0%E6%8D%AE/1.htm">导数据</a>
                                    <div>解决mysql导入导出数据乱码问题方法: 
 
1、进入mysql,通过如下命令查看数据库编码方式: 
 
mysql>  show variables like 'character_set_%'; 
+--------------------------+----------------------------------------+ 
| Variable_name&nbs</div>
                                </li>
                                <li><a href="/article/2558.htm"
                                       title="SAE部署Smarty出现:Uncaught exception 'SmartyException' with message 'unable to write" target="_blank">SAE部署Smarty出现:Uncaught exception 'SmartyException' with message 'unable to write</a>
                                    <span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a><a class="tag" taget="_blank" href="/search/smarty/1.htm">smarty</a><a class="tag" taget="_blank" href="/search/sae/1.htm">sae</a>
                                    <div>  
对于SAE出现的问题:Uncaught exception 'SmartyException' with message 'unable to write file...。 
官方给出了详细的FAQ:http://sae.sina.com.cn/?m=faqs&catId=11#show_213 
解决方案为: 
        
01  
$path </div>
                                </li>
                                <li><a href="/article/2685.htm"
                                       title="《教父》系列台词" target="_blank">《教父》系列台词</a>
                                    <span class="text-muted">dcj3sjt126com</span>

                                    <div>Your love is also your weak point. 
你的所爱同时也是你的弱点。 
  
If anything in this life is certain, if history has taught us anything, it is 
that you can kill anyone. 
  
不顾家的人永远不可能成为一个真正的男人。 &</div>
                                </li>
                                <li><a href="/article/2812.htm"
                                       title="mongodb安装与使用" target="_blank">mongodb安装与使用</a>
                                    <span class="text-muted">dyy_gusi</span>
<a class="tag" taget="_blank" href="/search/mongo/1.htm">mongo</a>
                                    <div>一.MongoDB安装和启动,widndows和linux基本相同 
1.下载数据库, 
    linux:mongodb-linux-x86_64-ubuntu1404-3.0.3.tgz 
2.解压文件,并且放置到合适的位置 
    tar -vxf mongodb-linux-x86_64-ubun</div>
                                </li>
                                <li><a href="/article/2939.htm"
                                       title="Git排除目录" target="_blank">Git排除目录</a>
                                    <span class="text-muted">geeksun</span>
<a class="tag" taget="_blank" href="/search/git/1.htm">git</a>
                                    <div>在Git的版本控制中,可能有些文件是不需要加入控制的,那我们在提交代码时就需要忽略这些文件,下面讲讲应该怎么给Git配置一些忽略规则。 
  
有三种方法可以忽略掉这些文件,这三种方法都能达到目的,只不过适用情景不一样。 
1.  针对单一工程排除文件 
这种方式会让这个工程的所有修改者在克隆代码的同时,也能克隆到过滤规则,而不用自己再写一份,这就能保证所有修改者应用的都是同一</div>
                                </li>
                                <li><a href="/article/3066.htm"
                                       title="Ubuntu 创建开机自启动脚本的方法" target="_blank">Ubuntu 创建开机自启动脚本的方法</a>
                                    <span class="text-muted">hongtoushizi</span>
<a class="tag" taget="_blank" href="/search/ubuntu/1.htm">ubuntu</a>
                                    <div>转载自: http://rongjih.blog.163.com/blog/static/33574461201111504843245/ 
Ubuntu 创建开机自启动脚本的步骤如下:  
1) 将你的启动脚本复制到 /etc/init.d目录下   以下假设你的脚本文件名为 test。       
2) 设置脚本文件的权限    $ sudo chmod 755</div>
                                </li>
                                <li><a href="/article/3193.htm"
                                       title="第八章 流量复制/AB测试/协程" target="_blank">第八章 流量复制/AB测试/协程</a>
                                    <span class="text-muted">jinnianshilongnian</span>
<a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a><a class="tag" taget="_blank" href="/search/lua/1.htm">lua</a><a class="tag" taget="_blank" href="/search/coroutine/1.htm">coroutine</a>
                                    <div>流量复制 
在实际开发中经常涉及到项目的升级,而该升级不能简单的上线就完事了,需要验证该升级是否兼容老的上线,因此可能需要并行运行两个项目一段时间进行数据比对和校验,待没问题后再进行上线。这其实就需要进行流量复制,把流量复制到其他服务器上,一种方式是使用如tcpcopy引流;另外我们还可以使用nginx的HttpLuaModule模块中的ngx.location.capture_multi进行并发</div>
                                </li>
                                <li><a href="/article/3320.htm"
                                       title="电商系统商品表设计" target="_blank">电商系统商品表设计</a>
                                    <span class="text-muted">lkl</span>

                                    <div>DROP TABLE IF EXISTS `category`; -- 类目表
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `category` (
  `id` int(11) NOT NUL</div>
                                </li>
                                <li><a href="/article/3447.htm"
                                       title="修改phpMyAdmin导入SQL文件的大小限制" target="_blank">修改phpMyAdmin导入SQL文件的大小限制</a>
                                    <span class="text-muted">pda158</span>
<a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a>
                                    <div> 用phpMyAdmin导入mysql数据库时,我的10M的 
数据库不能导入,提示mysql数据库最大只能导入2M。      
phpMyAdmin数据库导入出错:     You probably tried to upload too large file. Please refer to documentation for ways to workaround this limit.  </div>
                                </li>
                                <li><a href="/article/3574.htm"
                                       title="Tomcat性能调优方案" target="_blank">Tomcat性能调优方案</a>
                                    <span class="text-muted">Sobfist</span>
<a class="tag" taget="_blank" href="/search/apache/1.htm">apache</a><a class="tag" taget="_blank" href="/search/jvm/1.htm">jvm</a><a class="tag" taget="_blank" href="/search/tomcat/1.htm">tomcat</a><a class="tag" taget="_blank" href="/search/%E5%BA%94%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">应用服务器</a>
                                    <div>一、操作系统调优 
 对于操作系统优化来说,是尽可能的增大可使用的内存容量、提高CPU的频率,保证文件系统的读写速率等。经过压力测试验证,在并发连接很多的情况下,CPU的处理能力越强,系统运行速度越快。。 
 【适用场景】 任何项目。 
 二、Java虚拟机调优 
 应该选择SUN的JVM,在满足项目需要的前提下,尽量选用版本较高的JVM,一般来说高版本产品在速度和效率上比低版本会有改进。 
 J</div>
                                </li>
                                <li><a href="/article/3701.htm"
                                       title="SQLServer学习笔记" target="_blank">SQLServer学习笔记</a>
                                    <span class="text-muted">vipbooks</span>
<a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/xml/1.htm">xml</a>
                                    <div>1、create database school 创建数据库school 
 
2、drop database school 删除数据库school 
 
3、use school 连接到school数据库,使其成为当前数据库 
 
4、create table class(classID int primary key identity not null) 
 创建一个名为class的表,其有一</div>
                                </li>
                </ul>
            </div>
        </div>
    </div>

<div>
    <div class="container">
        <div class="indexes">
            <strong>按字母分类:</strong>
            <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a
                href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a
                href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a
                href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a
                href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a
                href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a
                href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a
                href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a
                href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a>
        </div>
    </div>
</div>
<footer id="footer" class="mb30 mt30">
    <div class="container">
        <div class="footBglm">
            <a target="_blank" href="/">首页</a> -
            <a target="_blank" href="/custom/about.htm">关于我们</a> -
            <a target="_blank" href="/search/Java/1.htm">站内搜索</a> -
            <a target="_blank" href="/sitemap.txt">Sitemap</a> -
            <a target="_blank" href="/custom/delete.htm">侵权投诉</a>
        </div>
        <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved.
<!--            <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>-->
        </div>
    </div>
</footer>
<!-- 代码高亮 -->
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script>
<link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/>
<script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script>





</body>

</html>