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/1891659937948430336.htm"
                           title="webpack 项目优化(一)" target="_blank">webpack 项目优化(一)</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/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a>
                        <div>一、构建速度优化缩小文件处理范围module:{rules:[{test:/\.js$/,exclude:/node_modules/,//排除第三方库include:path.resolve(__dirname,'src'),//限定处理范围use:'babel-loader'}]}利用缓存Webpack5+内置持久化缓存(直接配置):cache:{type:'filesystem'}//大幅提</div>
                    </li>
                    <li><a href="/article/1891653255944007680.htm"
                           title="前端构建工具——Webpack和Vite的主要区别" target="_blank">前端构建工具——Webpack和Vite的主要区别</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/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/webpack/1.htm">webpack</a>
                        <div>目录1.设计理念2.性能表现3.使用场景4.配置复杂度5.生态系统6.性能对比总结7.选择建议1.设计理念Webpack设计理念:Webpack是一个通用的模块打包工具,它将项目中的各种资源(如JavaScript、CSS、图片等)视为模块,并通过loader和plugin进行处理和打包。适用范围:适用于复杂项目,支持高度定制化,适合需要精细控制构建过程的场景。Vite设计理念:Vite(法语“快</div>
                    </li>
                    <li><a href="/article/1891647067072294912.htm"
                           title="包管理工具npm、yarn、pnpm、cnpm详解" target="_blank">包管理工具npm、yarn、pnpm、cnpm详解</a>
                        <span class="text-muted">懒羊羊我小弟</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E5%B7%A5%E7%A8%8B%E5%8C%96/1.htm">前端工程化</a><a class="tag" taget="_blank" href="/search/npm/1.htm">npm</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/yarn/1.htm">yarn</a><a class="tag" taget="_blank" href="/search/cnpm/1.htm">cnpm</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a>
                        <div>1.包管理工具1.1npm#安装$node自带npm#基本用法npminstallpackage#安装包npminstall#安装所有依赖npminstall-gpackage#全局安装npmuninstallpackage#卸载包npmupdatepackage#更新包npmrunscript#运行脚本#特点-Node.js默认包管理器-依赖平铺结构-包安装慢-磁盘空间占用大1.2yarn#安装</div>
                    </li>
                    <li><a href="/article/1891644920318455808.htm"
                           title="学习笔记分享-快速掌握前端-html进阶(利用telnet发送json请求、利用telnet发送multipart请求)" target="_blank">学习笔记分享-快速掌握前端-html进阶(利用telnet发送json请求、利用telnet发送multipart请求)</a>
                        <span class="text-muted">2301_81243975</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a>
                        <div>前言图片上面的personal表示只有图片上面的一行语句是解释图片内容的、local表示这个图片所在标题下的所有语句都是解释图片内容的、global表示有多个标题下的所有语句都是解释图片内容的我是一名大二的学生,学了差不多一年java技术栈了,想记录一下自己对知识点的心得,目前还是个小白,期望大佬们可以指出我笔记中的不足之处、对知识点的认知错误、笔记结构的混乱等这些图片内容都是在观看黑马课程时的视</div>
                    </li>
                    <li><a href="/article/1891642776697761792.htm"
                           title="Webpack 基础入门" target="_blank">Webpack 基础入门</a>
                        <span class="text-muted">懒羊羊我小弟</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E5%B7%A5%E7%A8%8B%E5%8C%96/1.htm">前端工程化</a><a class="tag" taget="_blank" href="/search/webpack/1.htm">webpack</a><a class="tag" taget="_blank" href="/search/rust/1.htm">rust</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/es6/1.htm">es6</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a>
                        <div>一、Webpack是什么Webpack是一款现代JavaScript应用程序的静态模块打包工具。在Web开发中,我们的项目会包含各种类型的文件,如JavaScript、CSS、图片等。Webpack可以将这些文件打包成一个或多个文件,以便在浏览器中高效加载。它就像是一个超级管家,把项目中的各种资源整理打包,让它们能更好地协同工作。二、为什么要使用Webpack代码拆分:可以将代码拆分成多个块,实现</div>
                    </li>
                    <li><a href="/article/1891641135756013568.htm"
                           title="【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(四) -> 常见组件(二) -> tabs" target="_blank">【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(四) -> 常见组件(二) -> tabs</a>
                        <span class="text-muted">枫叶丹4</span>
<a class="tag" taget="_blank" href="/search/HarmonyOS/1.htm">HarmonyOS</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><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/harmonyos/1.htm">harmonyos</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BA/1.htm">华为</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BA%E4%BA%91/1.htm">华为云</a>
                        <div>目录1->创建Tabs2->设置Tabs方向3->设置样式4->显示页签索引5->场景示例1->创建Tabs在pages/index目录下的hml文件中创建一个Tabs组件。item1item2content1content2/*test.css*/.container{flex-direction:column;justify-content:center;align-items:center;</div>
                    </li>
                    <li><a href="/article/1891636979590819840.htm"
                           title="html放大镜效果代码,原生JS实现的放大镜效果实例代码" target="_blank">html放大镜效果代码,原生JS实现的放大镜效果实例代码</a>
                        <span class="text-muted">看热闹不嫌事大菌</span>
<a class="tag" taget="_blank" href="/search/html%E6%94%BE%E5%A4%A7%E9%95%9C%E6%95%88%E6%9E%9C%E4%BB%A3%E7%A0%81/1.htm">html放大镜效果代码</a>
                        <div>js放大镜效果*{margin:0px;padding:0px;border:none;list-style:none;}#box{margin:80pxauto;width:352px;}#boxp{width:350px;height:350px;border:1pxsolid#ddd;margin-bottom:5px;}#boxpimg{width:350px;height:350px;}</div>
                    </li>
                    <li><a href="/article/1891628655122116608.htm"
                           title="Electron常见问题 4-error: The engine “node“ is incompatible with this module." target="_blank">Electron常见问题 4-error: The engine “node“ is incompatible with this module.</a>
                        <span class="text-muted">Data-Mining</span>
<a class="tag" taget="_blank" href="/search/Electron%E5%AE%9E%E6%88%98/1.htm">Electron实战</a><a class="tag" taget="_blank" href="/search/builder/1.htm">builder</a><a class="tag" taget="_blank" href="/search/electron/1.htm">electron</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E8%AF%91/1.htm">编译</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a><a class="tag" taget="_blank" href="/search/yarn/1.htm">yarn</a>
                        <div>目录问题解决PS:《Electron实战》系列-总览问题Electron工程编译的时候报错:errorelectron-builder@20.44.4:Theengine"node"isincompatiblewiththismodule.Expectedversion">=8.12.0".Got"8.11.3"errorFoundincompatiblemodule.解决原因是nodejs版本冲</div>
                    </li>
                    <li><a href="/article/1891628273658556416.htm"
                           title="NPM如何更换淘宝镜像——Node.js国内镜像配置教程" target="_blank">NPM如何更换淘宝镜像——Node.js国内镜像配置教程</a>
                        <span class="text-muted">孽小倩</span>
<a class="tag" taget="_blank" href="/search/nodejs/1.htm">nodejs</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a><a class="tag" taget="_blank" href="/search/npm/1.htm">npm</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>在国内使用npm安装Node.js包时,由于网络环境的原因,下载速度可能非常慢。为了解决这个问题,很多开发者会选择使用淘宝镜像(现在由npmmirror.com维护)。本文将带你一步一步完成更换npm源为淘宝镜像的配置,提升安装速度。一、为什么要更换淘宝镜像?默认情况下,npm使用的是官方源,这个源的速度在国内相对较慢,特别是在一些需要下载大量依赖的情况下,可能会出现下载失败或者等待时间过长的情况</div>
                    </li>
                    <li><a href="/article/1891626631714369536.htm"
                           title="探索Node.js的原生插件新境界:使用`node-gyp`" target="_blank">探索Node.js的原生插件新境界:使用`node-gyp`</a>
                        <span class="text-muted">洪新龙</span>

                        <div>探索Node.js的原生插件新境界:使用node-gypnode-gypNode.jsnativeaddonbuildtool项目地址:https://gitcode.com/gh_mirrors/no/node-gyp在Node.js的生态系统中,将高性能的C/C++代码融入到JavaScript世界已经成为提升应用性能的关键手段。今天,我们要向大家隆重推荐一个不可或缺的工具——node-gyp</div>
                    </li>
                    <li><a href="/article/1891624865522315264.htm"
                           title="贪吃蛇案例" target="_blank">贪吃蛇案例</a>
                        <span class="text-muted">The_era_achievs_hero</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>题十:贪吃蛇还原要求:只需对所给js代码的部分函数进行还原最终实现效果即可原理:首先获得蛇的头部定位,再根据键盘改变头部的位置。更新蛇的身体数组,删除蛇身体的最后一个元素,并生成新数组(头部作为新数组的第一个元素)//移动蛇的头部nextStep(){//TODO:待补充代码////只需完善该函数实现功能,不允许修改别处代码//使用对象展开运算符,复制当前蛇的头部位置consthead={...t</div>
                    </li>
                    <li><a href="/article/1891624613050380288.htm"
                           title="_05JavaScript" target="_blank">_05JavaScript</a>
                        <span class="text-muted">The_era_achievs_hero</span>
<a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/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/js/1.htm">js</a>
                        <div>第五次网课1.JavaScript的书写位置内部JS//页面弹出警示框alert('你好,js~')外部JS(最多)内联(行内)(以后vue框架会用这种模式)点我月薪过万2.JavaScript的注释与结束符单行注释符号://ctrl+/多行注释符号:/**/shift+alt+a结束符用;表示结束可写可不写,要么全都写,要么全不写vue.js不加分号3.JavaScript的输入输出语法输出中文</div>
                    </li>
                    <li><a href="/article/1891622091707445248.htm"
                           title="全面了解 Node.js、npm、yarn、node-gyp、Python、Visual Studio 和 Electron 的关联性" target="_blank">全面了解 Node.js、npm、yarn、node-gyp、Python、Visual Studio 和 Electron 的关联性</a>
                        <span class="text-muted">古木12345</span>
<a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a><a class="tag" taget="_blank" href="/search/npm/1.htm">npm</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/electron/1.htm">electron</a><a class="tag" taget="_blank" href="/search/yarn/1.htm">yarn</a>
                        <div>好的,以下是一个全面且深入的详细解析,针对Electron桌面开发工具链及其相关依赖,包含每个关键模块(Node.js、npm、yarn、Python、node-gyp、VisualStudio、Electron)及其实现原理、功能、关联性和使用示例,确保您能完整理解这些工具的用途和关联性。一、基础工具链模块详细介绍1.Node.js1.1功能概述Node.js是一个运行时环境,它允许开发者在服务</div>
                    </li>
                    <li><a href="/article/1891610360276905984.htm"
                           title="【Three.js】四(1)、three.js中的光源——基础光源" target="_blank">【Three.js】四(1)、three.js中的光源——基础光源</a>
                        <span class="text-muted">MAXLZ</span>
<a class="tag" taget="_blank" href="/search/%E3%80%90WebGL%E3%80%91Three.js/1.htm">【WebGL】Three.js</a><a class="tag" taget="_blank" href="/search/three.js/1.htm">three.js</a><a class="tag" taget="_blank" href="/search/%E5%85%89%E6%BA%90/1.htm">光源</a><a class="tag" taget="_blank" href="/search/AmbientLight/1.htm">AmbientLight</a><a class="tag" taget="_blank" href="/search/PointLight/1.htm">PointLight</a><a class="tag" taget="_blank" href="/search/SpotLight/1.htm">SpotLight</a>
                        <div>【Three.js】四(1)、three.js中的光源——基础光源一、THREE.AmbientLight二、THREE.PointLight2.1THREE.PointLight属性三、THREE.SpotLight3.1THREE.SpotLight属性四、THREE.DirectionalLight4.1THREE.DirectionalLight的属性three.js中的光源有:THREE</div>
                    </li>
                    <li><a href="/article/1891604280536788992.htm"
                           title="初识redux" target="_blank">初识redux</a>
                        <span class="text-muted">未命名小孩</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E7%9F%A5%E8%AF%86/1.htm">前端知识</a><a class="tag" taget="_blank" href="/search/react/1.htm">react</a><a class="tag" taget="_blank" href="/search/js/1.htm">js</a><a class="tag" taget="_blank" href="/search/typescript/1.htm">typescript</a>
                        <div>Redux是一个用于管理JavaScript应用程序状态的可预测状态容器核心概念1.单一数据源整个应用的状态被存储在一个单一的对象树(store)中,这个对象树位于唯一的store里。创建store:conststore=createStore(reducer)2.状态是只读的唯一改变状态的方法是触发一个action,action是一个描述状态变化的纯对象。这保证了所有的状态变化都是可追踪的。一个</div>
                    </li>
                    <li><a href="/article/1891603396813713408.htm"
                           title="如果 main 里面引入 axios ,然后引入 router ,而 router 里面也引入 axios,会不会重复" target="_blank">如果 main 里面引入 axios ,然后引入 router ,而 router 里面也引入 axios,会不会重复</a>
                        <span class="text-muted">清风细雨_林木木</span>
<a class="tag" taget="_blank" href="/search/%E6%8A%80%E6%9C%AF%E7%82%B9/1.htm">技术点</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><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>技术点备忘如果main里面引入axios,然后引入router,而router里面也引入axios,会不会重复不会重复的。虽然你在main中引入了axios,并且在router中也引入了axios,但引入的axios是同一个模块。JavaScript的模块系统是基于单例模式的,意思是每个模块只会被加载一次,之后的引用都会指向同一个实例。具体来说:当你在main.js中引入axios,它会在模块加载</div>
                    </li>
                    <li><a href="/article/1891598733334867968.htm"
                           title="Python之json模块的序列化和反序列化" target="_blank">Python之json模块的序列化和反序列化</a>
                        <span class="text-muted">如梦@_@</span>
<a class="tag" taget="_blank" href="/search/python%E5%9F%BA%E7%A1%80/1.htm">python基础</a>
                        <div>序列化:可以理解为压缩反序列化:可以理解为解压Python中序列化和反序列化其实就是一个正反两个过程。序列化就是将Python对象转化为json格式,因为Python对象只有Python语言能够识别,如果想把数据发给Java代码写的程序,那么就识别不了,所以就有一个中间的格式:json,Java中也是一样,就是将Java的数据类型转换成json格式。反序列化就是,Python接收数据的应该是Pyt</div>
                    </li>
                    <li><a href="/article/1891598607077928960.htm"
                           title="java使用递归获取geojson(json)数据" target="_blank">java使用递归获取geojson(json)数据</a>
                        <span class="text-muted">迷茫的小猿</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/json/1.htm">json</a>
                        <div>需要导入的包:org.json-chargebee-1.0.jarpackageparse;importjava.io.BufferedReader;importjava.io.BufferedWriter;importjava.io.FileReader;importjava.io.FileWriter;importjava.io.IOException;importjava.util.Arra</div>
                    </li>
                    <li><a href="/article/1891597219736383488.htm"
                           title="geojson 导入mysql_导入GeoJSON数据到SQL Server数据库中" target="_blank">geojson 导入mysql_导入GeoJSON数据到SQL Server数据库中</a>
                        <span class="text-muted">冠位咕哒子</span>
<a class="tag" taget="_blank" href="/search/geojson/1.htm">geojson</a><a class="tag" taget="_blank" href="/search/%E5%AF%BC%E5%85%A5mysql/1.htm">导入mysql</a>
                        <div>导入GeoJSON数据到SQLServer数据库中GeoJSON是GIS行业里一种常见的数据交换格式,能够存储结构化的空间地理信息。因为SQLServer从2008版开始提供了空间数据类型geometry与geography的支持,所以我也试着将项目中用到的地图数据转换到数据库中,方便之后的调用。因为中途遇到了不少坑,所以写了这篇文章作为备忘。事前准备:了解GeoJSON与SQLServer的空间</div>
                    </li>
                    <li><a href="/article/1891595947813695488.htm"
                           title="C#、ASP、ASP.NET、.NET、ASP.NET CORE区别、ASP.NET Core其概念和特点、ASP.NET Core个人心得体会" target="_blank">C#、ASP、ASP.NET、.NET、ASP.NET CORE区别、ASP.NET Core其概念和特点、ASP.NET Core个人心得体会</a>
                        <span class="text-muted">手中的风筝664</span>
<a class="tag" taget="_blank" href="/search/c%23/1.htm">c#</a><a class="tag" taget="_blank" href="/search/asp.net/1.htm">asp.net</a><a class="tag" taget="_blank" href="/search/.net/1.htm">.net</a>
                        <div>C#是一种面向对象的编程语言,主要用于开发跨平台的应用程序。它是.NET框架的一部分,并且可以在.NET平台上运行。ASP(ActiveServerPages)是一种用于构建动态Web页面的技术,使用VBScript或JScript作为服务器端脚本语言。它是早期的Microsoft技术,现已逐渐过时。ASP.NET是微软推出的下一代Web应用程序开发技术,它提供了更强大、更高效的功能和工具。ASP</div>
                    </li>
                    <li><a href="/article/1891595192302104576.htm"
                           title="在nodejs中使用RabbitMQ(四)队列类型Classic、Quorum、Stream" target="_blank">在nodejs中使用RabbitMQ(四)队列类型Classic、Quorum、Stream</a>
                        <span class="text-muted">konglong127</span>
<a class="tag" taget="_blank" href="/search/nodejs/1.htm">nodejs</a><a class="tag" taget="_blank" href="/search/rabbitmq/1.htm">rabbitmq</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a>
                        <div>经典队列(ClassicQueues)、仲裁队列(QuorumQueues)和流队列(StreamQueues)——的特性对比表:FeatureClassicQueuesQuorumQueuesStreamQueuesNon-durablequeues(非持久队列)YesNoNoMessagereplication(消息复制)NoYesNoExclusivity(独占性)YesNoNoPermes</div>
                    </li>
                    <li><a href="/article/1891592542118539264.htm"
                           title="空间数据存储格式GeoJSON" target="_blank">空间数据存储格式GeoJSON</a>
                        <span class="text-muted">guokanglun</span>
<a class="tag" taget="_blank" href="/search/WebGIS%E5%BC%80%E5%8F%91/1.htm">WebGIS开发</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>GeoJSON是一种用于表示地理信息的开放标准格式,广泛用于存储和交换地理空间数据。它基于JSON格式,因此易于理解和处理,尤其适用于Web和JavaScript环境中的地图应用。GeoJSON支持多种地理信息类型,如点、线、面、坐标系统等。GeoJSON基本结构GeoJSON文件本质上是一个JSON对象,通常包含以下几个主要部分:type:指定GeoJSON数据的类型。features:一个包含</div>
                    </li>
                    <li><a href="/article/1891587629460287488.htm"
                           title="如何在Python中进行JSON数据的序列化和反序列化?" target="_blank">如何在Python中进行JSON数据的序列化和反序列化?</a>
                        <span class="text-muted">计算机学长大白</span>
<a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>在Python中,JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。Python内置的json模块提供了简单易用的方法来实现数据的序列化和反序列化。下面将详细介绍如何在Python中进行JSON数据的序列化和反序列化,并给出具体的示例。1.序列化序列化是指将Python对象转换为JSON格式的字符串。json模块提供</div>
                    </li>
                    <li><a href="/article/1891570599508111360.htm"
                           title="爬虫实践——selenium、bs4" target="_blank">爬虫实践——selenium、bs4</a>
                        <span class="text-muted">lucky_chaichai</span>
<a class="tag" taget="_blank" href="/search/Python%E7%88%AC%E8%99%AB/1.htm">Python爬虫</a><a class="tag" taget="_blank" href="/search/selenium/1.htm">selenium</a><a class="tag" taget="_blank" href="/search/requests/1.htm">requests</a><a class="tag" taget="_blank" href="/search/%E7%88%AC%E8%99%AB/1.htm">爬虫</a><a class="tag" taget="_blank" href="/search/selenium/1.htm">selenium</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a>
                        <div>目录一、浏览器的一般设置二、打开网页并获取网页源码的方式1、基于requests库2、基于urlib库3、基于selenium三、HTML解析1、BeautifulSoup2、Selenium动态渲染爬虫:模拟动态操作网页,加载JS(webdriver)3、scrapy框架四、反爬虫操作五、一些常见的异常处理六、url接口调用问题——get、post操作1、get请求2、post请求fromsel</div>
                    </li>
                    <li><a href="/article/1891563911170289664.htm"
                           title="uniapp uni-icons组件自定义图标" target="_blank">uniapp uni-icons组件自定义图标</a>
                        <span class="text-muted">xcLeigh</span>
<a class="tag" taget="_blank" href="/search/uniapp%E6%8A%80%E6%9C%AF%E7%82%B9%E8%A7%A3%E6%9E%90/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%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                        <div>文章目录1️⃣uni-icons组件1.1引用位置1.2FontEditor简介1.2FontEditor使用结束语优质源码分享uni-app是一个使用Vue.js(opensnewwindow)开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序、快应用等多个平台。1️⃣uni-icons组件1.1引用位置1.2FontEditor简介Fo</div>
                    </li>
                    <li><a href="/article/1891563280082726912.htm"
                           title="【MongoDB】MongoDb的“not master and slaveok=false”错误及解决方法" target="_blank">【MongoDB】MongoDb的“not master and slaveok=false”错误及解决方法</a>
                        <span class="text-muted">weixin_30900589</span>
<a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/shell/1.htm">shell</a>
                        <div>链接mongodb报错如下2016-03-14T16:26:00.912+0800EQUERY[thread1]Error:listDatabasesfailed:{"ok":0,"errmsg":"notmasterandslaveOk=false","code":13435}:_getErrorWithCode@src/mongo/shell/utils.js:23:13Mongo.proto</div>
                    </li>
                    <li><a href="/article/1891563280896421888.htm"
                           title="【MongoDB】MongoDb的“not master and slaveok=false”错误及解决方法 mongo连接从库出现问题..." target="_blank">【MongoDB】MongoDb的“not master and slaveok=false”错误及解决方法 mongo连接从库出现问题...</a>
                        <span class="text-muted">weixin_33782386</span>
<a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/shell/1.htm">shell</a><a class="tag" taget="_blank" href="/search/php/1.htm">php</a>
                        <div>链接mongodb报错如下2016-03-14T16:26:00.912+0800EQUERY[thread1]Error:listDatabasesfailed:{"ok":0,"errmsg":"notmasterandslaveOk=false","code":13435}:_getErrorWithCode@src/mongo/shell/utils.js:23:13Mongo.proto</div>
                    </li>
                    <li><a href="/article/1891559237344096256.htm"
                           title="leaflet手绘地图实现原理-可视化工具设计手绘地图" target="_blank">leaflet手绘地图实现原理-可视化工具设计手绘地图</a>
                        <span class="text-muted">diygwcom</span>
<a class="tag" taget="_blank" href="/search/leaflet/1.htm">leaflet</a><a class="tag" taget="_blank" href="/search/%E6%89%8B%E7%BB%98%E5%9C%B0%E5%9B%BE/1.htm">手绘地图</a><a class="tag" taget="_blank" href="/search/%E8%87%AA%E5%AE%9A%E4%B9%89%E5%9C%B0%E5%9B%BE%E7%93%A6%E7%89%87/1.htm">自定义地图瓦片</a>
                        <div>在Leaflet中实现手绘地图并添加自定义标注是一个有趣且实用的功能。Leaflet是一个开源的JavaScript库,用于在网页上创建交互式地图。下面是一个基本的实现步骤,包括如何加载手绘地图和添加自定义标注。步骤1:设置HTML页面首先,创建一个基本的HTML页面,并引入Leaflet库。Leaflet手绘地图与自定义标注#map{height:100vh;}//JavaScript代码将在这</div>
                    </li>
                    <li><a href="/article/1891553815396675584.htm"
                           title="js根据指定字符截取字符串(正则方式)" target="_blank">js根据指定字符截取字符串(正则方式)</a>
                        <span class="text-muted">i'm wxm</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><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>1、截取两个字符之间的字符串varstr="aaabbbcccdddeeefff";str=str.match(/aaa(\S*)fff/)[1];alert(str);//结果bbbcccdddeee2、截取指定字符串前varstr="这个是一句话";str=str.match(/(\S*)是/)[1];alert(str);//结果--->这个3、截取指定字符后varstr="这个是一句话";</div>
                    </li>
                    <li><a href="/article/1891553815996461056.htm"
                           title="js判断当前时间是否在指定范围内" target="_blank">js判断当前时间是否在指定范围内</a>
                        <span class="text-muted">i'm wxm</span>
<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><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>一、js判断当前时间是否在指定范围内利用js的Date对象,获得三个时间戳,分别为当前时间、开始时间、结束时间,通过比对当前时间是否在开始时间和结束时间之间,来判断是否在一个时间区间内方法一:functionisTimeInRange(startTime:any,endTime:any){//获取当前时间、开始时间、结束时间的时间戳constnow=newDate();constcurrentTi</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>