0%

1. npm 是什么

NPM 的全称是 Node Package Manager,是随同 NodeJS 一起安装的包管理和分发工具,它很方便让 JavaScript 开发者下载、安装、上传以及管理已经安装的包。

2. npm install 安装模块

基础语法

1
2
3
4
5
6
7
8
9
10
11
npm install (with no args, in package dir)
npm install [<@scope>/]<name>
npm install [<@scope>/]<name>@<tag>
npm install [<@scope>/]<name>@<version>
npm install [<@scope>/]<name>@<version range>
npm install <tarball file>
npm install <tarball url>
npm install <folder>

alias: npm i
common options: [-S|--save|-D|--save-dev|-O|--save-optional] [-E|--save-exact] [--dry-run]

安装包,默认会安装最新的版本

1
npm install gulp

image
安装指定版本

1
npm install gulp@3.9.1

安装包并将信息保持到项目的 package.json 文件中

image

项目对模块的依赖可以使用下面的 3 种方法来表示(假设当前版本号是 1.1.0 ):

  • 兼容模块新发布的补丁版本:~1.1.0、1.1.x、1.1
  • 兼容模块新发布的小版本、补丁版本:^1.1.0、1.x、1
  • 兼容模块新发布的大版本、小版本、补丁版本:*、x

-S, –save 安装包信息将加入到 dependencies(生产阶段的依赖)

1
npm install gulp --save 或 npm install gulp -S

package.json 文件的 dependencies 字段:

1
2
3
"dependencies": {
"gulp": "^3.9.1"
}

-D, –save-dev 安装包信息将加入到 devDependencies(开发阶段的依赖),所以开发阶段一般使用它

1
npm install gulp --save-dev 或 npm install gulp -D

package.json 文件的 devDependencies 字段:

1
2
3
"devDependencies": {
"gulp": "^3.9.1"
}

-O, –save-optional 安装包信息将加入到 optionalDependencies(可选阶段的依赖)

1
npm install gulp --save-optional 或 npm install gulp -O

package.json 文件的 optionalDependencies 字段:

1
2
3
"optionalDependencies": {
"gulp": "^3.9.1"
}

-E, –save-exact 精确安装指定模块版本

1
npm install gulp --save-exact 或 npm install gulp -E

输入命令npm install gulp -ES,留意 package.json 文件的 dependencies 字段,可以看出版本号中的^消失了

1
2
3
"dependencies": {
"gulp": "3.9.1"
}

模块的依赖都被写入了 package.json 文件后,他人打开项目的根目录(项目开源、内部团队合作),使用 npm install 命令可以根据 dependencies 配置安装所有的依赖包

1
npm install

image
本地安装(local)

1
npm install gulp

全局安装(global),使用 -g 或 –global

1
npm install gulp -g

3. npm uninstall 卸载模块

基础语法

1
2
3
npm uninstall [<@scope>/]<pkg>[@<version>]... [-S|--save|-D|--save-dev|-O|--save-optional]

aliases: remove, rm, r, un, unlink

如卸载开发版本的模块

1
npm uninstall gulp --save-dev

4. npm update 更新模块

基础语法

1
npm update [-g] [<pkg>...]

5. npm update [-g] […]

基础语法

1
npm outdated [[<@scope>/]<pkg> ...]

此命令会列出所有已经过时的包,可以及时进行包的更新

image

npm ls 查看安装的模块

基础语法

1
2
3
npm ls [[<@scope>/]<pkg> ...]

aliases: list, la, ll

查看全局安装的模块及依赖

1
npm ls -g

6. npm init 在项目中引导创建一个 package.json 文件

安装包的信息可保持到项目的 package.json 文件中,以便后续的其它的项目开发或者他人合作使用,也说 package.json 在项目中是必不可少的。

1
npm init [-f|--force|-y|--yes]

image

7. npm help 查看某条命令的详细帮助

基础语法

1
npm help <term> [<terms..>]

例如输入 npm help install,系统在默认的浏览器或者默认的编辑器中打开本地 nodejs 安装包的文件/nodejs/node_modules/npm/html/doc/cli/npm-install.html

1
npm help install

8. npm root 查看包的安装路径

输出 node_modules 的路径

1
npm root [-g]

9. npm config 管理 npm 的配置路径

基础语法

1
2
3
4
5
6
7
npm config set <key> <value> [-g|--global]
npm config get <key>
npm config delete <key>
npm config list
npm config edit
npm get <key>
npm set <key> <value> [-g|--global]

对于 config 这块用得最多应该是设置代理,解决 npm 安装一些模块失败的问题
例如我在公司内网,因为公司的防火墙原因,无法完成任何模块的安装,这个时候设置代理可以解决

1
npm config set proxy=http://xxx

又如国内的网络环境问题,某官方的 IP 可能被和谐了,幸好国内有好心人,搭建了镜像,此时我们简单设置镜像

1
npm config set registry="http://r.cnpmjs.org"

也可以临时配置,如安装淘宝镜像

1
也可以临时配置,如安装淘宝镜像

10. npm cache 管理模块的缓存

基础语法

1
2
3
4
5
6
7
8
npm cache add <tarball file>
npm cache add <folder>
npm cache add <tarball url>
npm cache add <name>@<version>

npm cache ls [<path>]

npm cache clean [<path>]

最常用命令无非清除 npm 本地缓存

1
npm cache clean

11. npm start 启动模块

基础语法

1
npm start [-- <args>]

该命令写在 package.json 文件 scripts 的 start 字段中,可以自定义命令来配置一个服务器环境和安装一系列的必要程序,如

1
2
3
"scripts": {
"start": "gulp -ws"
}

此时在 cmd 中输入 npm start 命令相当于执行 gulpfile.js 文件自定义的 watch 和 server 命令。

如果 package.json 文件没有设置 start,则将直接启动 node server.js

12. npm stop 停止模块

基础语法

1
npm stop [-- <args>]

13. npm restart 重新启动模块

基础语法

1
npm restart [-- <args>]

14. npm test 测试模块

基础语法

1
2
npm test [-- <args>]
npm tst [-- <args>]

该命令写在 package.json 文件 scripts 的 test 字段中,可以自定义该命令来执行一些操作,如

1
2
3
"scripts": {
"test": "gulp release"
},

此时在 cmd 中输入 npm test 命令相当于执行 gulpfile.js 文件自定义的 release 命令。

15. npm version 查看模块版本

基础语法

1
2
3
4
5
npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]

'npm [-v | --version]' to print npm version
'npm view <pkg> version' to view a package's published version
'npm ls' to inspect current package/dependency versions

查看模块的版本

1
npm version

image

16. npm view 查看模块的注册信息

基础语法

1
2
3
npm view [<@scope>/]<name>[@<version>] [<field>[.<subfield>]...]

aliases: info, show, v

查看模块的依赖关系

1
npm view gulp dependencies

查看模块的源文件地址

1
npm view gulp repository.url

查看模块的贡献者,包含邮箱地址

1
npm view npm contributors

17. npm adduser 用户登录

基础语法

1
npm adduser [--registry=url] [--scope=@orgname] [--always-auth]

image

发布模板到 npm 社区前需要先登录,然后再进入发布的操作

18. npm publish 发布模块

基础语法

1
2
3
4
npm publish [<tarball>|<folder>] [--tag <tag>] [--access <public|restricted>]

Publishes '.' if no argument supplied
Sets tag 'latest' if no --tag specified

image

19. npm access 在发布的包上设置访问级别

基础语法

1
2
3
4
5
6
7
8
9
npm access public [<package>]
npm access restricted [<package>]

npm access grant <read-only|read-write> <scope:team> [<package>]
npm access revoke <scope:team> [<package>]

npm access ls-packages [<user>|<scope>|<scope:team>]
npm access ls-collaborators [<package> [<user>]]
npm access edit [<package>]

20. npm package.json 的语法

默认值

npm 会根据包内容设置一些默认值。

  • “scripts”: {“start”: “node server.js”}

如果包的根目录有 server.js 文件,npm 会默认将 start 命令设置为 node server.js。

  • “scripts”:{“preinstall”: “node-waf clean || true; node-waf configure build”}

如果包的根目录有 wscript 文件,npm 会默认将 preinstall 命令用 node-waf 进行编译。

  • “scripts”:{“preinstall”: “node-gyp rebuild”}

如果包的根目录有 binding.gyp 文件,npm 会默认将 preinstall 命令用 node-gyp 进行编译。

  • “contributors”: […]

如果包的根目录有 AUTHORS 文件,npm 会默认逐行按 Name (url)格式处理,邮箱和 url 是可选的。#号和空格开头的行会被忽略。

name

在 package.json 中最重要的就是 name 和 version 字段。他们都是必须的,如果没有就无法 install。name 和 version 一起组成的标识在假设中是唯一的。改变包应该同时改变 version。

name 是这个东西的名字。注意:

  • 不要把 node 或者 js 放在名字中。因为你写了 package.json 它就被假定成为了 js,不过你可以用”engine”字段指定一个引擎(见后文)。
  • 这个名字会作为在 URL 的一部分、命令行的参数或者文件夹的名字。任何 non-url-safe 的字符都是不能用的。
  • 这个名字可能会作为参数被传入 require(),所以它应该比较短,但也要意义清晰。
  • 在你爱上你的名字之前,你可能要去 npm registry 查看一下这个名字是否已经被使用了。http://registry.npmjs.org/

version

version 必须能被 node-semver 解析,它被包在 npm 的依赖中。(要自己用可以执行 npm install semver)

可用的“数字”或者“范围”见 semver(7).

description

放简介,字符串,方便在 npm search 中搜索

keywords

关键字,数组、字符串,方便在 npm search 中搜索

bugs

你项目的提交问题的 url 和(或)邮件地址

1
2
3
4
{
"url" : "http://github.com/owner/project/issues",
"email" : "project@hostname.com"
}

license

你应该要指定一个许可证,让人知道使用的权利和限制的。

最简单的方法是,假如你用一个像 BSD 或者 MIT 这样通用的许可证,就只需要指定一个许可证的名字,像这样:

1
{ "license" : "BSD" }

如果你有更复杂的许可条件,或者想要提供给更多地细节,可以这样:

1
2
3
"licenses" : [
{ "type" : "MyLicense", "url" : "http://github.com/owner/project/path/to/license" }
]

repository

指定你的代码存放的地方。这个对希望贡献的人有帮助。如果 git 仓库在 github 上,那么 npm docs 命令能找到你。

这样做:

1
2
3
4
5
6
7
8
9
"repository" :
{ "type" : "git"
, "url" : "http://github.com/isaacs/npm.git"
}

"repository" :
{ "type" : "svn"
, "url" : "http://v8.googlecode.com/svn/trunk/"
}

URL 应该是公开的(即便是只读的)能直接被未经过修改的版本控制程序处理的 url。不应该是一个 html 的项目页面。因为它是给计算机看的。

scripts

“scripts”是一个由脚本命令组成的 hash 对象,他们在包不同的生命周期中被执行。key 是生命周期事件,value 是要运行的命令。

参考上面的 npm start、npm test 命令

更多详细请看 npm-scripts(7)

config

“config” hash 可以用来配置用于包脚本中的跨版本参数。在实例中,如果一个包有下面的配置:

1
2
3
4
{
"name" : "foo",
"config" : { "port" : "8080" }
}

然后有一个“start”命令引用了 npm_package_config_port 环境变量,用户可以通过 npm config set foo:port 8001 来重写他。

参见 npm-config(7) 和 npm-scripts(7)。

dependencies

依赖是给一组包名指定版本范围的一个 hash。这个版本范围是一个由一个或多个空格分隔的字符串。依赖还可以用 tarball 或者 git URL。

请不要将测试或过渡性的依赖放在 dependencieshash 中。见下文的 devDependencies

详见 semver(7).

  • version 必须完全和 version 一致
  • version 必须比 version 大

  • =version 同上

  • <version 同上
  • <=version 同上
  • ~version 大约一样,见 semver(7)
  • 1.2.x 1.2.0, 1.2.1, 等,但不包括 1.3.0
  • http://… 见下文’依赖 URL’
    • 所有
  • “” 空,同*
  • version1 - version2 同 >=version1 <=version2.
  • range1 || range2 二选一。
  • git… 见下文’依赖 Git URL’
  • user/repo 见下文’GitHub URLs’

比如下面都是合法的:

1
2
3
4
5
6
7
8
9
10
11
12
13
{ "dependencies" :
{ "foo" : "1.0.0 - 2.9999.9999"
, "bar" : ">=1.0.2 <2.1.2"
, "baz" : ">1.0.2 <=2.3.4"
, "boo" : "2.0.1"
, "qux" : "<1.0.0 || >=2.3.1 <2.4.5 || >=2.5.2 <3.0.0"
, "asd" : "http://asdf.com/asdf.tar.gz"
, "til" : "~1.2"
, "elf" : "~1.2.3"
, "two" : "2.x"
, "thr" : "3.3.x"
}
}

devDependencies

如果有人要使用你的模块,那么他们可能不需要你开发使用的外部测试或者文档框架。

在这种情况下,最好将这些附属的项目列在 devDependencies 中。

这些东西会在执行 npm link 或者 npm install 的时候初始化,并可以像其他 npm 配置参数一样管理。详见 npm-config(7)。

对于非特定平台的构建步骤,比如需要编译 CoffeeScript,可以用 prepublish 脚本去实现,并把它依赖的包放在 devDependency 中。(译者注:prepublish 定义了在执行 npm publish 的时候先行执行的脚本)

比如:

1
2
3
4
5
6
7
8
9
10
11
{ "name": "ethopia-waza",
"description": "a delightfully fruity coffee varietal",
"version": "1.2.3",
"devDependencies": {
"coffee-script": "~1.6.3"
},
"scripts": {
"prepublish": "coffee -o lib/ -c src/waza.coffee"
},
"main": "lib/waza.js"
}

prepublish 脚本会在 publishing 前运行,这样用户就不用自己去 require 来编译就能使用。并且在开发模式中(比如本地运行 npm install)会运行这个脚本以便更好地测试。

1.Linux 管理文件和目录的命令

命令 功能 命令 功能
pwd 显示当前目录 ls 查看目录下的内容
cd 改变所在目录 cat 显示文件的内容
grep 在文件中查找某字符 cp 复制文件
touch 创建文件 mv 移动文件
rm 删除文件 rmdir 删除目录
vi 编辑文件

1.1 pwd 命令

该命令的英文解释为 print working directory(打印工作目录)。输入 pwd 命令,Linux 会输出当前目录。

1.2 cd 命令

cd 命令用来改变所在目录。

1
2
3
4
cd /      转到根目录中
cd ~ 转到/home/user用户目录下
cd /usr 转到根目录下的usr目录中-------------绝对路径
cd test 转到当前目录下的test子目录中-------相对路径

1.3 ls 命令

ls 命令用来查看目录的内容。

选项 含义
-a 列举目录中的全部文件,包括隐藏文件
-l 列举目录中的细节,包括权限、所有者、组群、大小、创建日期、文件是否是链接等
-f 列举的文件显示文件类型
-r 逆向,从后向前地列举目录中内容
-R 递归,该选项递归地列举当前目录下所有子目录内的内容
-s 大小,按文件大小排序
-h 以人类可读的方式显示文件的大小,如用 K、M、G 作单位
ls -l examples.doc 列举文件 examples.doc 的所有信息

1.4 cat 命令

cat 命令可以用来合并文件,也可以用来在屏幕上显示整个文件的内容。

cat snow.txt 该命令显示文件 snow.txt 的内容,ctrl+D 退出 cat。

1.5 grep 命令

grep 命令的最大功能是在一堆文件中查找一个特定的字符串。

grep money test.txt

以上命令在 test.txt 中查找 money 这个字符串,grep 查找是区分大小写的。

1.6 touch 命令

touch 命令用来创建新文件,他可以创建一个空白的文件,可以在其中添加文本和数据。

touch newfile 该命令创建一个名为 newfile 的空白文件。

1.7 cp 命令

cp 命令用来拷贝文件,要复制文件,输入命令:

cp

cp t.txt Document/t 该命令将把文件 t.txt 复制到 Document 目录下,并命名为 t。

选项 含义
-i 互动:如果文件将覆盖目标中的文件,他会提示确认
-r 递归:这个选项会复制整个目录树、子目录以及其他
-v 详细:显示文件的复制进度

1.8 mv 命令

mv 命令用来移动文件。

选项 说明
-i 互动:如果选择的文件会覆盖目标中的文件,他会提示确认
-f 强制:它会超越互动模式,不提示地移动文件,属于很危险的选项
-v 详细:显示文件的移动进度

mv t.txt Document 把文件 t.txt 移动到目录 Document 中。

1.9 rm 命令

rm 命令用来删除文件。

选项 说明
-i 互动:提示确认删除
-f 强制:代替互动模式,不提示确认删除
-v 详细:显示文件的删除进度
-r 递归:将删除某个目录以及其中所有的文件和子目录

rm t.txt 该命令删除文件 t.txt

1.10 rmdir 命令

rmdir 命令用来删除目录。

1.11 vi 编辑文件(补充)

vi 命令是 UNIX 操作系统和类 UNIX 操作系统中最通用的全屏幕纯文本编辑器。Linux 中的 vi 编辑器叫 vim,它是 vi 的增强版(vi Improved),与 vi 编辑器完全兼容,而且实现了很多增强功能。

进入 vi 的命令

1
2
3
4
5
vi filename :打开或新建文件,并将光标置于第一行首
vi n filename :打开文件,并将光标置于第n行首
vi /pattern filename:打开文件,并将光标置于第一个与pattern匹配的串处
vi -r filename :在上次正用vi编辑时发生系统崩溃,恢复filename
vi filename....filename :打开多个文件,依次进行编辑

屏幕翻滚类命令

1
2
3
4
5
Ctrl u:向文件首翻半屏
Ctrl d:向文件尾翻半屏
Ctrl f:向文件尾翻一屏
Ctrl+b;向文件首翻一屏
nz:将第n行滚至屏幕顶部,不指定n时将当前行滚至屏幕顶部.

插入文本类命令

1
2
3
4
5
6
7
8
9
i :在光标前
I :在当前行首
a:光标后
A:在当前行尾
o:在当前行之下新开一行
O:在当前行之上新开一行
r:替换当前字符
R:替换当前字符及其后的字符,直至按ESC键
s:从当前光标位置处开始,以输入的文本替代指定数目的字符

保存命令

1
2
3
4
5
6
7
8
9
10
按ESC键 跳到命令模式,然后:

:w 保存文件但不退出vi
:w file 将修改另外保存到file中,不退出vi
:w! 强制保存,不推出vi
:wq 保存文件并退出vi
:wq! 强制保存文件,并退出vi
:q 不保存文件,退出vi
:q! 不保存文件,强制退出vi
:e! 放弃所有修改,从上次保存文件开始再编辑

之后,回车,ok!

2.有关磁盘空间的命令

命令 功能
mount 挂载文件系统
umount 卸载已挂载上的文件系统
df 检查各个硬盘分区和已挂上来的文件系统的磁盘空间
du 显示文件目录和大小
fsck 主要是检查和修复 Linux 文件系统

2.1 mount 命令

1
2
3
4
mount命令的功能是挂载文件系统,可以挂载硬盘、光盘、软盘,也可以挂载NFS网络文件系统。这个命令的标准用法如下:

mount –t 设备类型存放目录
mount IP地址:/所提供的目录存放目录
选项 说明
(无) 不加任何参数,直接输入命令可以显示已挂载的文件系统和目录
-a 挂上/etc/fstab 下的全部文件系统
-t 指定所挂上来的文件系统的名称,所有系统支持的文件系统,这个信息可以在/proc/filesystems 这个文件里看到
-n 挂上文件系统,但是不把文件系统的数据写入/etc/mtlab 这个文件
-w 将文件系统设为可读写
-r 挂上来的文件系统设为只读

在目录/mnt 下,挂上 iso9660 文件系统。输入命令:

1
mount –t iso9660 /dev/hdb /cdrom

2.2 umount 命令

umount 命令的功能是卸载已挂上的文件系统,在关闭系统前应该把所有挂载上的文件系统卸载。这个命令和 mount 命令是相对的。用法:

umount 已挂上的目录或设备

卸载已挂上的/cdrom 目录,输入命令:

umount /cdrom

卸载已挂上的某个分区,输入命令:

umount /dev/hdb1

2.3 df 命令

df 命令用来检查硬盘分区和已挂载的文件系统的磁盘空间,也就是说,检查硬盘的使用量。标准用法如下:

df [-选项]

选项 功能
-a 把全部的文件系统和各分区的硬盘使用情形列出来,包括 0 区块的,例如/proc 这个文件系统
-i 列出 I-nodes 的使用量
-k 把各分区的大小和挂上来的文件分区的大小用 k 表示
-t 列出某一文件系统的所有分区磁盘空间使用量
-x 列出不是某一文件系统的所有分区磁盘空间使用量,和-t 选项相反
-T 列出每个分区所属文件系统的名称

例如,要列出全部文件系统和各分区的磁盘使用情况,输入命令:

df –a

2.4 du 命令

du 命令的功能是用于显示文件目录或大小。标准用法:

du [-选项]

选项 含义
-a 显示全部目录及其次目录下的每个文件所占的磁盘空间
-b 显示目录和文件的大小,以 B 为单位
-c 最后再加上一个总计
-h 以 KB、MB、GB 为单位,提高信息可读性
-s 只列出各文件大小的总和
-x 只计算属于同一文件系统的文件

2.5 fsck 命令

fsck 命令的功能是检查和修复 Linux 文件系统,这个命令最好在没有人或是没有分区挂上来时使用,其实每次开机系统都会做一次检查,看是否有坏轨或数据流失的现象。用法:

fsck (-选项) 分区名称

选项 功能
-a 自动修复文件系统,不询问任何问题,比较危险
-A 依照/etc/fstab 配置文件的内容,检查该文件内所列全部文件系统。若没有附加参数”-P”,则会先检查/目录的文件系统,而不会同时检查所有文件系统
-R 采取互动方式,在修复时询问问题,让用户确认并决定处理方式
-S 依次检查作业而不是同时执行。当依次指定多个文件系统且采用互动的方式进行检查时,请使用此参数以便顺序执行,否则 fsck 可能会同时询问数个问题,让人不知所措
-V 显示命令执行的过程
-T 指定要检查的文件系统的类型
-N 不是真正执行指令,仅列出实际执行时会进行的动作

3.文件备份和压缩命令

在 Linux 中,常用的文件压缩工具有 gzip、bzip2、zip。bzip2 是最理想的压缩工具,它提供了最大限度的压缩。zip 兼容性好,Windows 也支持。

命令 功能
bzip2/bunzip2 扩展名为 bz2 的压缩/解压缩工具
gzip/gunzip 扩展名为 gz 的压缩/解压缩工具
zip/unzip 扩展名为 zip 的压缩/解压缩工具
tar 创建备份和归档

3.1 bzip2 命令

要使用 bzip2 来压缩文件,在 shell 提示下输入命令:

bzip2 filename

文件即会被压缩,并被保存为 filename.bz2。

要解压缩文件,输入命令:

bunzip2 filename.bz2

filename.bz2 会被删除,而以 filename 代替。

bzip2 filename.bz2 file1 file2 file3/usr/work/school

上面的命令把 file1、file2、file3 以及/usr/work/school 目录中的内容压缩起来放入 filename.bz2。

3.2 gzip 命令

要使用 gzip 来压缩文件,输入命令:

gzip filename

文件即会被压缩,并被保存为 filename.gz。

要解压缩文件,输入命令:

gunzip filename.gz

filename.gz 会被删除,而以 filename 代替。

gzip -r filename.gz file1 file2 file3/usr/work/school

上面的命令把 file1、file2、file3 以及/usr/work/school 目录中的内容压缩起来放入 filename.gz。

3.3 zip 命令

zip 命令的使用方法同 gzip。

3.4 tar 命令

tar 命令最早是用来做磁带备份的,但是由于硬盘容量越来越大,因此现在主要用这个命令来备份所有的文件。tar 这个命令把大量的文件和目录打包成一个文件。

选项 功能
-c 创建一个新归档
-f 当与-c 选项一起使用时,创建的 tar 文件使用该选项指定的文件名;当与-x 选项一起使用时,则解除该选项指定的归档
-t 显示包括在 tar 文件中的文件列表
-v 显示文件的归档进度
-x 从归档中抽取文件
-z 使用 gzip 压缩 tar 文件
-j 使用 bzip2 压缩 tar 文件

要创建一个 tar 文件,输入命令:

tar –cvf filename.tar directory/file/home/mine

上面的命令将 directory/file、/home/mine 放入归档文件中。

要列出 tar 文件的内容,输入命令:

tar –tvf filename.tar

要抽取 tar 文件的命令,输入命令:

tar –xvf filename.tar

这个命令不会删除 tar 文件,但会把解除归档的内容复制到当前工作目录下,并保留归档文件所使用的任何目录结构。

请记住,tar 默认不压缩文件。要创建一个使用 tar 和 bzip2 来归档压缩的文件,使用-j 选项:

tar –cjvf filename.tbz file

如果使用 bunzip2 命令解压 filename.tbz 文件,则 filename.tbz 会被删除,以 filename.tar 代替。

要扩展并解除归档 bzip tar 文件,输入命令:

tar –xjvf filename.tbz

要创建一个用 tar 和 gzip 归档并压缩的文件,使用-z 选项:

tar –czvf filename.tgz file

如果使用 gunzip 命令解压 filename.tgz 文件,则 filename.tgz 会被删除,以 filename.tar 代替。

4.有关关机和查看系统信息的命令

命令 说明
shutdown 正常关机
reboot 重启计算机
ps 查看目前程序执行的情况
top 查看目前程序执行的情景和内存使用的情况
kill 终止一个进程
date 更改或查看目前日期
cal 显示月历及年历

4.1 shutdown 命令

要使用这个命令必须保证是根用户,否则使用 su 命令改变为根用户。命令格式如下:

shutdown –(选项)

选项 功能
-k 不是真正的关机,只是发出警告命令
-r 关机后重启(这个用的最多)
-t 在规定的时间内关机

加入要在 2min 内关机,输入命令:

shutdown –t 2

如果是关机后重启,输入命令:

shutdown –r

4.2 reboot 命令

这个命令也是一个关机命令,只有输入,不加任何参数,系统会以最快的速度关机,且不将内存或缓冲区里的东西写回硬盘。

选项 功能
-d 不把记录写到/var/log/wtmp 档案里(-n 这个参数包含了-d)
-f 不把记录写到/var/log/wtmp 档案里(-n 这个参数包含了-d)
-n 在重开机前不做将记忆体资料写回硬盘
-w 并不会真的重开机,只是把记录写到/var/log/wtmp 档案里

4.3 ps 命令

ps 命令用来查看在计算机系统中有哪些程序正在执行,及其执行的情况。这是一个相当强大的命令,可以用它来找出所有的 process id 和名称。另外,ps 命令也可以用来列出所有程序占用内存的情况。用法如下:

ps –(选项)

选项 功能
-l 用长格式列出
-u 列出使用者的名称和使用时间
-m 列出内存分布的情况
-r 只列出正在执行的前台程序,不列出其他信息
-x 列出所有程序,包括那些没有终端机的程序

4.4 top 命令

top 命令可以查看目前程序的执行情景和内存使用。它和 ps 类似,不过,它会几秒钟更新一次系统状态,方便追踪。要离开这个程序,按 Ctrl+C 键就可以了。

4.5 kill 命令

kill 命令用来终止一个正在执行中的进程。如果一个程序执行过程中失败了,可以把这个程序终止,避免留在内存中占用系统资源。不过,它的实际意义是送一个信号给这个正在执行的程序,叫它自杀。可以送很多信号给这些程序,也可以让他们收到信号后做很多事情。标准用法:

kill –(选项) pid

在执行 kill 命令前。可以先用 ps 命令查一下某宕掉程序的 pid,然后使用 kill 除去某个程序。例如,终止 pid 为 90 的程序:

kill 90

选项 选项
-l 列出所有可用的信号名称
-p 印出 pid 并不发送信号
-signal 其中可用的讯号有 HUP (1), KILL (9), TERM (15), 分别代表着重跑, 砍掉, 结束

将 pid 为 323 的行程砍掉 (kill) :

kill -9 323

将 pid 为 456 的行程重跑 (restart) :

kill -HUP 456

4.6 date 命令

date 命令用来显示、设定和修改现在的时间和日期。标准用法:

date –(选项) 显示时间格式(以+号开头,后加格式)
date 设定时间格式

选项 功能
-u 使用格林尼治时间
-r 最后一次修改文件的时间
-s 设置时间

常用的几种时间格式如下表所示:

格式 说明
%a 星期几的简称,例如一、二、三
%A 星期几的全名,例如星期一、星期二
%D 日期(mm/dd/yy 格式)
%T 显示时间格式,24 小时制(hh:mm:ss)
%x 显示日期的格式(mm/dd/yy)
%y 年的最后两个数字
%Y 年(如 2007、2008)
%r 时间(hh:mm:ss 上午或下午)
%p 显示上午或下午

如果输入命令:

date “+%x,%r”

系统返回如下信息:

2010 年 3 月 26 日,下午 18 时 06 分 49 秒

4.7 cal 命令

cal 命令有两种功能:显示月历以及年历。

直接输入 cal 命令则系统会显示目前月份的月历。

若要显示一整年的年历,可以在 cal 命令后加 4 位数的公元年份。例如要显示 2008 年的年历,必须输入:

cal 2008

若输入 cal 08 ,则最显示公元 8 年的年历。

若只需要查看某一年份中某一月份的月历,可以输入:cal 月份公元年份。例如输入:”cal 12 2004”。

5.管理使用者和设立权限的命令

命令 说明 命令 说明
chmod 用来改变权限 useradd 用来增加用户
su 用来修改用户

5.1 chmod 命令

chmod 命令用来改变许可权限。读取、写入和执行是许可权限中的三个主要设置。因为用户在他们的账号被创建时就被编入一个组群,所以还可以指定那些组群可以读取、写入或执行某一文件。其中:

r—文件可以被读取
w—文件可以被写入
x—文件可以被执行,如果文件是程序的话

可以使用带有-l 的 ls 命令来仔细查看一个文件的许多细节。

chmod 命令用来设定文件的权限。标准用法:

chmod 文件的使用者(u,g,o,a)增减(+,-,=)权限名称(r,w,x) 文件

文件的使用者 说明 权限 说明 增减 说明
u 拥有文件的用户 r 读取权 + 添加权限
g 所有者所在的组群 w 写入权 - 删除权限
o 其他人 x 执行权 = 是它称为唯一权限
a 全部(u,g 和 o)

删除某一文件的所有权限,输入命令:

chmod a-rwx test.txt

为文件所有者添加权限,输入命令:

chmod u+rwx test

还可以用数字表示权限:4——读取,2——写入,1——执行。下面的两个命令等价:

chmod 751 filename
chmod u+rwx,g=rx,0=x filename

5.2 su 命令

su 命令用来修改用户。这个命令非常重要,它可以让一个普通的使用者拥有超级用户或其他使用者的权限。不过,这个命令必须具有超级用户或其他使用者的口令才能成为超级用户或其他使用者。如果要离开,可以输入 exit。标准用法:

su 用户名 (如果没有输入用户名则预设为 root)

举例说明,假设当前用户 user01,想要转变为 user02,则输入命令:

su user02

系统返回:

password:

此时,输入 user02 的指令,就会变为 user02。

5.3 useradd 命令

useradd 命令用来增加用户,只有根用户才能增加用户。如果没有登录为根用户,输入 su,再输入根口令即可。

要增加用户,输入命令:

useradd 用户名

然后,根据提示为新用户输入一个口令即可。

6.线上查询的命令

命令 功能
man 查询和解释一个命令的使用方法,以及这个命令的说明事项
locate 定位文件和目录
whatis 寻找某个命令的含义

6.1 man 命令

man 命令用来查询和解释一个命令的使用方法和这个命令的注意事项。这个查询在每个 Linux 上都有。通常,使用者只要输入命令 man 和这个命令的名称 shell 就会列出一份完整的说明。标准用法:

man 命令的名称

要查询 ls 命令的说明书页,输入命令:

man ls

要翻阅说明书页,可以使用 Page Up 和 Page Down 键,或使用空格键向后翻一页,使用 b 向前翻。要退出说明书页,输入命令 q。要在说明书页中搜索关键字,输入命令/和要搜索的关键字或短语,然后按 Enter 键即可。所有出现在说明书页中的关键字都会被突出显示,允许快速地阅读上下文中的关键字。

6.2 locate 命令

locate 命令的主要功能是定位文件和目录。有时候,只知道某一文件或目录存在,却不知道在哪儿,就可以用 locate 来定位文件和目录。使用 locate 命令,将会看到每一个包括搜索中间的文件和目录。例如,如果想要搜索带有 test 的这个词的文件,输入命令:

locate test

locate 命令使用数据库来定位带有 test 这个词的文件或目录。

6.3 whatis 命令

whatis 命令用来查询某个命令的含义。用法简单,也不需要什么参数,直接在 whatis 命令后加上所要查询的命令就可以了,但是却很实用。

要查询 mv 命令的含义,输入命令:

whatis mv

7.文件阅读的命令

命令 功能
head 查看文件的开头部分
tail 查看文件结尾的 10 行
less less 是一个分页工具,它允许一页一页地(或一个屏幕一个屏幕地)查看信息
more more 是一个分页工具,它允许一页一页地(或一个屏幕一个屏幕地)查看信息

7.1 head 命令

head 命令可以用来查看文件的开头部分。此命令的格式是:

head 文件名

默认设置,它只查看文件的前 10 行。但可以通过指定一个数字选项来改变要显示的行数,命令如下:

head –20 文件名

这个命令将会查看文件的前 20 行。

7.2 tail 命令

tail 命令和 head 命令恰恰相反。使用 tail 命令,可以查看文件结尾的 10 行。这有助于查看日志文件的最后 10 行来阅读重要的系统信息。还可以使用 tail 观察日志文件更新的过程。使用-f 选项,tail 会自动实时地把打开文件中的新信息显示到屏幕上。例如,要活跃地观察/var/log/messages,以根用户身份在 shell 下输入以下命令:

tail –f /var/log/messages

7.3 less 命令

less 命令与 more 命令相似。

7.4 more 命令

more 和 less 的主要区别是,less 允许使用箭头来前后移动,而 more 使用空格键和 b 键来前后移动。使用 ls 和 more 来列举/etc 目录下的内容:

ls –al /etc | more

要使用 more 在文本文件中搜索关键字,按/键并输入命令搜索条目:

/foo

使用空格键来先前翻阅页码。按 q 键退出。

more 命令标准格式为:

more [选项] [fileNames]

选项 含义
-num 一次显示的行数
-d 提示使用者,在画面下方显示[Press space to continue, q to quit.],如果使用者按错键,则会显示[Press h for instructions.]而不是哔声
-l 取消遇见特殊字元^L(送纸字元)时会暂停的功能
-f 计算行数时,以实际上的行数,而非自动换行过后的行数(有些单行字数太长的会被扩展为两行或两行以上)
-p 不以卷动的方式显示每一页,而是先清除荧幕后再显示内容
-c 跟-p 相似,不同的是先显示内容再清除其他旧资料
-s 当遇到有连续两行以上的空白行,就代换为一行的空白行
-u 不显示下引号(根据环境变数 TERM 指定的 terminal 而有所不同)
+/ 在每个档案显示前搜寻该字串(pattern),然后从该字串之后开始显示
+num 从第 num 行开始显示
fileNames 欲显示内容的档案,可为复数个数

例如:

more -s testfile 逐页显示 testfile 之档案内容,如有连续两行以上空白行则以一行空白行显示。
more +20 testfile 从第 20 行开始显示 testfile 之档案内容。

8.网络操作命令

命令 功能 命令 功能
ftp 传送文件 telnet 远端登陆
bye 结束连线并结束程序 rlogin 远端登入
ping 检测主机 netstat 显示网络状态

8.1 ftp 命令

ftp 命令用来传输文件,非常重要。如果在网络上看到一个很重要的文件,就可以用这个命令把那个文件传到自己的机器上来。

标准用法:

ftp (-选项) 主机名称或 IP 地址

选项 含义
-D 详细显示命令的执行过程,便于排错和分析程序的执行情况
-I 关闭互动模式,不询问任何问题
-G 关闭本地主机文件名称支持特殊字符的扩充特征
-N 不适用自动登录。FTP 在启动时,会尝试自动登录远端系统,它会从用户的转述目录中读取.netrc 文件的内容,以便自行登录。若该文件不存在,FTP 会放弃自动登录,并询问用户的账号名称
-V 显示命令的执行过程

举例说明,用 ftp 登录 ftp.dark.com 主机,输入命令:

ftp ftp.dark.com

注意:用户必须有相应的存取权限,否则不能从远程系统中获得文件或向远程系统中传输文件。为了使用 ftp 来传输文件,用户必须知道远程计算机上的合法用户名和口令。

8.2 bye 命令

在 ftp 模式下,输入 bye 即可中断目前的连线作业,并结束 ftp 的执行,没有选项。

8.3 ping 命令

执行 ping 命令,它会使用 ICMP 传输协议,发出要求回应的信息,若远程主机的网络没有什么问题,就会回应信息,因而得知该主机运作正常。

标准用法:

ping (-选项) 主机名称或 IP 地址

选项 含义
c 次数 设置完成要求回应的次数。ping 命令会反复发出信息,直到达到设定的次数为止
D 使用 Socket 的 SO_DEBUG 功能
F 大量而且快速地送网络封包给一台机器,看它的回应。一般不到几秒钟,送出去的封包就会超过两千个
I 秒数 指定收发信息的间隔时间,单位为 s,预置位 1s。与参数 f 不兼容
S bytes 设置数据包的大小。预设置为 56B,加上 8B ICMP 头文件,共 64B
R 忽略网关,直接将数据包送到远程主机上。如果该主机并非局域网的一份子,就会传回错误信息
Q 不显示命令的执行过程,只显示结果
V 详细显示命令的执行过程,包括非回应信息和其它信息
T 存活数值 设置存活数值 TTL 的大小。TTL 是 IP 协议包中的一个值,它告诉网络,数据包在网络中的时间是否太长而应被丢弃

举例说明,检测 des.bllod.net 主机网络功能是否正常,送出去的信息需完成 5 次回应,每次间隔 10s,数据包的大小为 512B,输入命令:

ping –c 5 –i 10 –s 504 –t 64 des.blood.net

8.4 telnet 命令

telnet 命令的主要功能是进行远程登录。该命令允许用户在使用 telnet 协议的远程计算机之间进行通信,用户可以通过网络在远程计算机上登录,就像登录到本地机上执行命令一样。为了通过 telnet 登录计算机,必须知道远程计算机上的合法用户名和口令。telnet 只为普通终端提供终端仿真,而不支持 X Window 等图形环境。

标准用法:

telnet 主机名或 IP

例如登录 IP 地址为 140.114.63.12 的计算机,输入命令:

telnet 140.114.63.12

一旦 telnet 成功连接到远程系统上,就显示登录信息,并提示用户输入用户名和口令。如果用户名和口令正确,就能成功登录并在远程系统上工作。用户结束了远程会话后,一定要确保使用 logout 命令退出远程系统。然后 telnet 报告远程会话被关闭,并返回到用户本地机的 shell 提示符下。

8.5 rlogin 命令

rlogin 也是用来远程登录的。它的英文含义是 remote login。该命令与 telnet 命令很相似,允许用户启动远程系统上的交互命令会话。用法:

rlogin (-选项) host

选项 含义
8 允许输入 8 位字符数据
e 为 rlogin 会话设置转义字符,默认的转义字符是“~”,用户可以指定一个文字字符或一个/nnn 形式的八进制数
E 停止任何转义字符。当与-8 选项一起使用时,它提供一个完全透明的链接
l 用户名称 指定要登入远端主机的用户名称
L 使用 litout 模式进行远端登入操作

例如,要登入别人的计算机。输入命令:

rlogin –l inin 140.114.125.24

8.6 netstat 命令

netstat 命令的主要功能是了解 Linux 系统的网络情况。假设没有指定任何参数给 netstat 命令,则效果和指定-F 参数相同。

用法:

netstat (-选项)

选项 说明
a 显示所有连线中的 Socket
F 显示 FIB
a 全部列出,包括正在等待的程序
c 持续列出网络状态
i 显示网络界面信息
n 使用网络 ip 地址代替名称
o 显示计时器
r 显示网络路径表
t 显示 TCP 协议的连接情形
u 显示 UDP 协议的连接情形
v 显示版本信息
w 显示 RAW 传输协议的连接情形

which

语法

which command

说明

依序从 path 环境变量所列的目录中找出 command 的位置,并显示完整路径的名称。在找到第一个符合条件的程序文件时,就立刻停止搜索,省略其余未搜索目录。

范例,找出 ls 命令的程序文件的位置:

which ls

系统输出:

/usr/bin/ls

whereis

语法

whereis [option] name

说明

找出特定程序的可执行文件、源代码文件以及 manpage 的路径。你所提供的 name 会被先除去前置的路径以及任何.ext 形式的扩展名。

whereis 只会在标准的 Linux 目录中进行搜索。

常用选项

-b

只搜索可执行文件。

-m

只搜索 manpage。

-s

只搜索源代码文件。

-B directory

更改或限定搜索可执行的文件的目录。

-M directory

更改或限定搜索 manpage 的目录。

-S directory

更改或限定搜索源代码文件的目录。

find

语法

find paths expression [action]

说明

以 paths 为搜索起点逐层往下找出每一个符合 expression 条件的文件,并对该文件执行 action 所代表的动作。expression 是搜索条件,它由一个代表匹配项目的选项以及一个代表匹配模式的参数构成。

action 是处理动作,它有一个代表“处理方式”的选项以及一个操作参数构成。若不指定 action,则默认动作是显示出文件名。

常用的搜索条件

-name pattern
-path pattern
-lname pattern

找出名称、路径名称或符号链接的目标匹配 pattern 模式的文件。pattern 可以包含 shell 的文件名通配符,路径是相对于搜索起点的。

常见处理动作

-print

显示出文件的相对路径(相对于搜索起点)。

-exec cmd /;

执行指定的 shell 命令。若 cmd 含有任何 shell 特殊字符,则他们之前都必须加上/符号,以免 shell 立刻执行他们。在 cmd 里,可以用”{}”符号(包括双引号)表示 find 所找出的文件。

locate

语法

locate patterns

说明

第一次执行 locate 时,它会建立一个索引数据库,当往后再次执行时,它便从索引数据库中迅速找出文件的位置。locate 很适合用来反复搜索很少变动的目录树,但是对于刚改名的旧文件以及新建的文件,locate 就找不到了,除非重建数据库。

updatedb

语法

updatedb [option]

说明

更新 slocate 的索引数据库。

选项

-e directories

略过 directories 所列的目录。

9.其他命令

命令 功能 命令 功能
echo 显示一字串 passwd 修改密码
clear 清除显示器 lpr 打印
lpq 查看在打印队列中等待的作业 lprm 取消打印队列中的作业

9.1 echo 命令

echo 命令用来在显示器上输出一段文字,这个命令常用来输出一些提示信息,因此这个命令的意义在于输出一些文字。它的用法也很简单:

echo –(参数) 字串 (可以用””,也可以不用,显示略有区别)

参数 n 代表输出文字后不换行,如果不加参数会自动换行。

输入命令:

echo “welcome to use Linux”

输出结果为:

welcome to use Linux

如果不加””,则输出结果为:

welcome to use Linux

它们的区别在于后一个输出,每两个输出之间只隔一个空格,这是因为 echo 把这些输出看做字串的缘故。

9.2 clear 命令

clear 命令的主要功能是清除显示器,这个命令很简单,只要输入 clear 即可。

9.3 passwd 命令

passwd 命令用来修改用户的密码。

在 shell 下输入

passwd

然后,根据提示输入旧密码和新密码即可。

9.4 lpr 命令

lpr 命令的功能是把指定的文件发送到打印队列中。例如,lpr foo.txt 会打印 foo.txt 文件。

标准用法:

lpr filename

要查看在打印队列中等待的作业,在命令行中输入命令 lpq。系统返回如下信息:

active root 389 foo.txt

在这个例子中,389 是作业号码。还可以取消打印队列中的作业,格式是:

lprm 作业号码

输入命令:

lprm 389

这样就去修改了 foo.txt 打印作业。

10.bash 常用命令

image

成功启动 MongoDB 后,再打开一个命令行窗口输入 mongo,就可以进行数据库的一些操作。输入 help 可以看到基本操作命令,只是 MongoDB 没有创建数据库的命令,但有类似的命令。

如:如果你想创建一个“myTest”的数据库,先运行 use myTest 命令,之后就做一些操作(如:db.createCollection(‘user’)),这样就可以创建一个名叫“myTest”的数据库。

一、数据库常用命令

1、Help 查看命令提示

1
2
3
4
5
help
db.help();
db.yourColl.help();
db.youColl.find().help();
rs.help();

2、切换/创建数据库

1
use yourDB; 当创建一个集合(table)的时候会自动创建当前数据库

3、查询所有数据库

1
show dbs;

4、删除当前使用数据库

1
db.dropDatabase();

5、从指定主机上克隆数据库

1
db.cloneDatabase(“127.0.0.1”); 将指定机器上的数据库的数据克隆到当前数据库

6、从指定的机器上复制指定数据库数据到某个数据库

1
db.copyDatabase("mydb", "temp", "127.0.0.1");将本机的mydb的数据复制到temp数据库中

7、修复当前数据库

1
db.repairDatabase();

8、查看当前使用的数据库

1
2
db.getName();
db; db和getName方法是一样的效果,都可以查询当前使用的数据库

9、显示当前 db 状态

1
db.stats();

10、当前 db 版本

1
db.version();

11、查看当前 db 的链接机器地址

1
db.getMongo();

二、Collection 聚集集合

1、创建一个聚集集合(table)

1
2
db.createCollection(“collName”, {size: 20, capped: 5, max: 100});//创建成功会显示{“ok”:1}
//判断集合是否为定容量db.collName.isCapped();

2、得到指定名称的聚集集合(table)

1
db.getCollection("account");

3、得到当前 db 的所有聚集集合

1
db.getCollectionNames();

4、显示当前 db 所有聚集索引的状态

1
db.printCollectionStats();

三、用户相关

1、添加一个用户

1
2
db.addUser("name");
db.addUser("userName", "pwd123", true); 添加用户、设置密码、是否只读

2、数据库认证、安全模式

1
db.auth("userName", "123123");

3、显示当前所有用户

1
show users;

4、删除用户

1
db.removeUser("userName");

四、聚集集合查询

1、查询所有记录

1
2
db.userInfo.find();
相当于:select* from userInfo;

默认每页显示 20 条记录,当显示不下的情况下,可以用 it 迭代命令查询下一页数据。注意:键入 it 命令不能带“;”
但是你可以设置每页显示数据的大小,用 DBQuery.shellBatchSize= 50;这样每页就显示 50 条记录了。

2、查询去掉后的当前聚集集合中的某列的重复数据

1
2
3
db.userInfo.distinct("name");
会过滤掉name中的相同数据
相当于:select distict name from userInfo;

3、查询 age = 22 的记录

1
2
db.userInfo.find({"age": 22});
相当于: select * from userInfo where age = 22;

4、查询 age > 22 的记录

1
2
db.userInfo.find({age: {$gt: 22}});
相当于:select * from userInfo where age >22;

5、查询 age < 22 的记录

1
2
db.userInfo.find({age: {$lt: 22}});
相当于:select * from userInfo where age <22;

6、查询 age >= 25 的记录

1
2
db.userInfo.find({age: {$gte: 25}});
相当于:select * from userInfo where age >= 25;

7、查询 age <= 25 的记录

1
db.userInfo.find({age: {$lte: 25}});

8、查询 age >= 23 并且 age <= 26

1
db.userInfo.find({age: {$gte: 23, $lte: 26}});

9、查询 name 中包含 mongo 的数据

1
2
3
db.userInfo.find({name: /mongo/});
//相当于%%
[code]select * from userInfo where name like ‘%mongo%';

10、查询 name 中以 mongo 开头的

1
2
db.userInfo.find({name: /^mongo/});
select * from userInfo where name like ‘mongo%';

11、查询指定列 name、age 数据

1
2
db.userInfo.find({}, {name: 1, age: 1});
相当于:select name, age from userInfo;

当然 name 也可以用 true 或 false,当用 true 的情况下和 name:1 效果一样,如果用 false 就是排除 name,显示 name 以外的列信息。

12、查询指定列 name、age 数据, age > 25

1
2
db.userInfo.find({age: {$gt: 25}}, {name: 1, age: 1});
相当于:select name, age from userInfo where age >25;

13、按照年龄排序

1
2
升序:db.userInfo.find().sort({age: 1});
降序:db.userInfo.find().sort({age: -1});

14、查询 name = zhangsan, age = 22 的数据

1
2
db.userInfo.find({name: 'zhangsan', age: 22});
相当于:select * from userInfo where name = ‘zhangsan' and age = ‘22';

15、查询前 5 条数据

1
2
db.userInfo.find().limit(5);
相当于:selecttop 5 * from userInfo;

16、查询 10 条以后的数据

1
2
3
4
db.userInfo.find().skip(10);
相当于:select * from userInfo where id not in (
selecttop 10 * from userInfo
);

17、查询在 5-10 之间的数据

1
db.userInfo.find().limit(10).skip(5);

可用于分页,limit 是 pageSize,skip 是第几页

18、or 与 查询

1
2
db.userInfo.find({$or: [{age: 22}, {age: 25}]});
相当于:select * from userInfo where age = 22 or age = 25;

19、查询第一条数据

1
2
3
db.userInfo.findOne();
相当于:selecttop 1 * from userInfo;
db.userInfo.find().limit(1);

20、查询某个结果集的记录条数

1
2
db.userInfo.find({age: {$gte: 25}}).count();
相当于:select count(*) from userInfo where age >= 20;

21、按照某列进行排序

1
2
db.userInfo.find({sex: {$exists: true}}).count();
相当于:select count(sex) from userInfo;

五、索引

1、创建索引

1
2
db.userInfo.ensureIndex({name: 1});
db.userInfo.ensureIndex({name: 1, ts: -1});

2、查询当前聚集集合所有索引

1
db.userInfo.getIndexes();

3、查看总索引记录大小

1
db.userInfo.totalIndexSize();

4、读取当前集合的所有 index 信息

1
db.users.reIndex();

5、删除指定索引

1
db.users.dropIndex("name_1");

6、删除所有索引

1
db.users.dropIndexes();

六、修改、添加、删除集合数据

1、添加

1
db.users.save({name: ‘zhangsan', age: 25, sex: true});

添加的数据的数据列,没有固定,根据添加的数据为准

2、修改

1
2
3
4
5
6
db.users.update({age: 25}, {$set: {name: 'changeName'}}, false, true);
相当于:update users set name = ‘changeName' where age = 25;
db.users.update({name: 'Lisi'}, {$inc: {age: 50}}, false, true);
相当于:update users set age = age + 50 where name = ‘Lisi';
db.users.update({name: 'Lisi'}, {$inc: {age: 50}, $set: {name: 'hoho'}}, false, true);
相当于:update users set age = age + 50, name = ‘hoho' where name = ‘Lisi';

3、删除

1
db.users.remove({age: 132});

4、查询修改删除

1
2
3
4
5
6
7
8
9
10
11
12
db.users.findAndModify({
    query: {age: {$gte: 25}},
    sort: {age: -1},
    update: {$set: {name: 'a2'}, $inc: {age: 2}},
    remove: true
});
db.runCommand({ findandmodify : "users",
    query: {age: {$gte: 25}},
    sort: {age: -1},
    update: {$set: {name: 'a2'}, $inc: {age: 2}},
    remove: true
});
1
2
3
4
5
6
7
8
9
10
11
12
update 或 remove 其中一个是必须的参数; 其他参数可选。
参数 详解 默认值
query 查询过滤条件 {}
sort 如果多个文档符合查询过滤条件,将以该参数指定的排列方式选择出排在首位的对象,该对象将被操作 {}
remove 若为true,被选中对象将在返回前被删除 N/A
update 一个 修改器对象
N/A
new 若为true,将返回修改后的对象而不是原始对象。在删除操作中,该参数被忽略。 false
fields 参见Retrieving a Subset of Fields (1.5.0+)
All fields
upsert 创建新对象若查询结果为空。 示例 (1.5.4+)
false

七、语句块操作

1、简单 Hello World

1
print("Hello World!");

这种写法调用了 print 函数,和直接写入”Hello World!”的效果是一样的;

2、将一个对象转换成 json

1
2
tojson(new Object());
tojson(new Object('a'));

3、循环添加数据

1
2
3
> for (var i = 0; i < 30; i++) {
... db.users.save({name: "u_" + i, age: 22 + i, sex: i % 2});
... };

这样就循环添加了 30 条数据,同样也可以省略括号的写法

1
> for (var i = 0; i < 30; i++) db.users.save({name: "u_" + i, age: 22 + i, sex: i % 2});

也是可以的,当你用 db.users.find()查询的时候,显示多条数据而无法一页显示的情况下,可以用 it 查看下一页的信息;

4、find 游标查询

1
2
3
4
>var cursor = db.users.find();
> while (cursor.hasNext()) {
    printjson(cursor.next());
}

这样就查询所有的 users 信息,同样可以这样写

1
2
var cursor = db.users.find();
while (cursor.hasNext()) { printjson(cursor.next); }

同样可以省略{}号

5、forEach 迭代循环

1
db.users.find().forEach(printjson);

forEach 中必须传递一个函数来处理每条迭代的数据信息

6、将 find 游标当数组处理

1
2
var cursor = db.users.find();
cursor[4];

取得下标索引为 4 的那条数据
既然可以当做数组处理,那么就可以获得它的长度:cursor.length();或者 cursor.count();
那样我们也可以用循环显示数据

1
for (var i = 0, len = c.length(); i < len; i++) printjson(c[i]);

7、将 find 游标转换成数组

1
2
> var arr = db.users.find().toArray();
> printjson(arr[2]);

用 toArray 方法将其转换为数组

8、定制我们自己的查询结果

只显示 age <= 28 的并且只显示 age 这列数据

1
2
db.users.find({age: {$lte: 28}}, {age: 1}).forEach(printjson);
db.users.find({age: {$lte: 28}}, {age: true}).forEach(printjson);

排除 age 的列

1
db.users.find({age: {$lte: 28}}, {age: false}).forEach(printjson);

9、forEach 传递函数显示信息

1
db.things.find({x:4}).forEach(function(x) {print(tojson(x));});

八、其他

1、查询之前的错误信息

1
db.getPrevError();

2、清除错误记录

1
db.resetError();

查看聚集集合基本信息

  1. 查看帮助 db.yourColl.help();
  2. 查询当前集合的数据条数 db.yourColl.count();
  3. 查看数据空间大小 db.userInfo.dataSize();
  4. 得到当前聚集集合所在的 db db.userInfo.getDB();
  5. 得到当前聚集的状态 db.userInfo.stats();
  6. 得到聚集集合总大小 db.userInfo.totalSize();
  7. 聚集集合储存空间大小 db.userInfo.storageSize();
  8. Shard 版本信息 db.userInfo.getShardVersion()
  9. 聚集集合重命名 db.userInfo.renameCollection(“users”); 将 userInfo 重命名为 users
  10. 删除当前聚集集合 db.userInfo.drop();
1
2
3
4
5
6
7
8
show dbs:显示数据库列表
show collections:显示当前数据库中的集合(类似关系数据库中的表)
show users:显示用户
use <db name>:切换当前数据库,这和MS-SQL里面的意思一样
db.help():显示数据库操作命令,里面有很多的命令
db.foo.help():显示集合操作命令,同样有很多的命令,foo指的是当前数据库下,一个叫foo的集合,并非真正意义上的命令
db.foo.find():对于当前数据库中的foo集合进行数据查找(由于没有条件,会列出所有数据)
db.foo.find( { a : 1 } ):对于当前数据库中的foo集合进行查找,条件是数据中有一个属性叫a,且a的值为1

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
1.基于内存的key-value数据库
2.基于c语言编写的,可以支持多种语言的api //set每秒11万次,取get 81000次
3.支持数据持久化
4.value可以是string,hash, list, set, sorted set

使用场景
1. 取最新n个数据的操作
2. 排行榜,取top n个数据 //最佳人气前10条
3. 精确的设置过期时间
4. 计数器
5. 实时系统, 反垃圾系统
6. pub, sub发布订阅构建实时消息系统
7. 构建消息队列
8. 缓存
cmd访问redis
redis-cli.exe -h 127.0.0.1 -p 6379


key
keys * 获取所有的key
select 0 选择第一个库
move myString 1 将当前的数据库key移动到某个数据库,目标库有,则不能移动
flush db 清除指定库
randomkey 随机key
type key 类型

set key1 value1 设置key
get key1 获取key
mset key1 value1 key2 value2 key3 value3
mget key1 key2 key3
del key1 删除key
exists key 判断是否存在key
expire key 10 10过期
pexpire key 1000 毫秒
persist key 删除过期时间

string
set name cxx
get name
getrange name 0 -1 字符串分段
getset name new_cxx 设置值,返回旧值
mset key1 key2 批量设置
mget key1 key2 批量获取
setnx key value 不存在就插入(not exists)
setex key time value 过期时间(expire)
setrange key index value 从index开始替换value
incr age 递增
incrby age 10 递增
decr age 递减
decrby age 10 递减
incrbyfloat 增减浮点数
append 追加
strlen 长度
getbit/setbit/bitcount/bitop 位操作

hash
hset myhash name cxx
hget myhash name
hmset myhash name cxx age 25 note "i am notes"
hmget myhash name age note
hgetall myhash 获取所有的
hexists myhash name 是否存在
hsetnx myhash score 100 设置不存在的
hincrby myhash id 1 递增
hdel myhash name 删除
hkeys myhash 只取key
hvals myhash 只取value
hlen myhash 长度

list
lpush mylist a b c 左插入
rpush mylist x y z 右插入
lrange mylist 0 -1 数据集合
lpop mylist 弹出元素
rpop mylist 弹出元素
llen mylist 长度
lrem mylist count value 删除
lindex mylist 2 指定索引的值
lset mylist 2 n 索引设值
ltrim mylist 0 4 删除key
linsert mylist before a 插入
linsert mylist after a 插入
rpoplpush list list2 转移列表的数据

set
sadd myset redis
smembers myset 数据集合
srem myset set1 删除
sismember myset set1 判断元素是否在集合中
scard key_name 个数
sdiff | sinter | sunion 操作:集合间运算:差集 | 交集 | 并集
srandmember 随机获取集合中的元素
spop 从集合中弹出一个元素

zset
zadd zset 1 one
zadd zset 2 two
zadd zset 3 three
zincrby zset 1 one 增长分数
zscore zset two 获取分数
zrange zset 0 -1 withscores 范围值
zrangebyscore zset 10 25 withscores 指定范围的值
zrangebyscore zset 10 25 withscores limit 1 2 分页
Zrevrangebyscore zset 10 25 withscores 指定范围的值
zcard zset 元素数量
Zcount zset 获得指定分数范围内的元素个数
Zrem zset one two 删除一个或多个元素
Zremrangebyrank zset 0 1 按照排名范围删除元素
Zremrangebyscore zset 0 1 按照分数范围删除元素
Zrank zset 0 -1 分数最小的元素排名为0
Zrevrank zset 0 -1 分数最大的元素排名为0
Zinterstore
zunionstore rank:last_week 7 rank:20150323 rank:20150324 rank:20150325 weights 1 1 1 1 1 1 1


排序:
sort mylist 排序
sort mylist alpha desc limit 0 2 字母排序
sort list by it:* desc by命令
sort list by it:* desc get it:* get参数
sort list by it:* desc get it:* store sorc:result sort命令之store参数:表示把sort查询的结果集保存起来

订阅与发布:
订阅频道:subscribe chat1
发布消息:publish chat1 "hell0 ni hao"
查看频道:pubsub channels
查看某个频道的订阅者数量: pubsub numsub chat1
退订指定频道: unsubscrible chat1 , punsubscribe java.*
订阅一组频道: psubscribe java.*

redis事务:
隔离性,原子性,
步骤: 开始事务,执行命令,提交事务
multi //开启事务
sadd myset a b c
sadd myset e f g
lpush mylist aa bb cc
lpush mylist dd ff gg

服务器管理
dump.rdb
appendonly.aof
//BgRewriteAof 异步执行一个aop(appendOnly file)文件重写
会创建当前一个AOF文件体积的优化版本

//BgSave 后台异步保存数据到磁盘,会在当前目录下创建文件dump.rdb
//save同步保存数据到磁盘,会阻塞主进程,别的客户端无法连接

//client kill 关闭客户端连接
//client list 列出所有的客户端

//给客户端设置一个名称
client setname myclient1
client getname

config get port
//configRewrite 对redis的配置文件进行改写rdb save 900 1save 300 10save 60 10000aop备份处理appendonly yes 开启持久化appendfsync everysec 每秒备份一次命令:bgsave异步保存数据到磁盘(快照保存)lastsave返回上次成功保存到磁盘的unix的时间戳shutdown同步保存到服务器并关闭redis服务器bgrewriteaof文件压缩处理(命令)

1) 远程仓库相关命令

检出仓库:$ git clone git://github.com/jquery/jquery.git

查看远程仓库:$ git remote -v

添加远程仓库:$ git remote add [name] [url]

删除远程仓库:$ git remote rm [name]

修改远程仓库:$ git remote set-url –push [name] [newUrl]

拉取远程仓库:$ git pull [remoteName] [localBranchName]

推送远程仓库:$ git push [remoteName] [localBranchName]

如果想把本地的某个分支 test 提交到远程仓库,并作为远程仓库的 master 分支,或者作为另外一个名叫 test 的分支,如下:

$git push origin test:master // 提交本地 test 分支作为远程的 master 分支

$git push origin test:test // 提交本地 test 分支作为远程的 test 分支

2)分支(branch)操作相关命令

查看本地分支:$ git branch

查看远程分支:$ git branch -r

创建本地分支:$ git branch [name] —-注意新分支创建后不会自动切换为当前分支

切换分支:$ git checkout [name]

创建新分支并立即切换到新分支:$ git checkout -b [name]

删除分支:$ git branch -d [name] —- -d 选项只能删除已经参与了合并的分支,对于未有合并的分支是无法删除的。如果想强制删除一个分支,可以使用-D 选项

合并分支:$ git merge [name] —-将名称为[name]的分支与当前分支合并

创建远程分支(本地分支 push 到远程):$ git push origin [name]

删除远程分支:$ git push origin :heads/[name] 或 $ git push origin :[name]

创建空的分支:(执行命令之前记得先提交你当前分支的修改,否则会被强制删干净没得后悔)

$git symbolic-ref HEAD refs/heads/[name]

$rm .git/index

$git clean -fdx

3)版本(tag)操作相关命令

查看版本:$ git tag

创建版本:$ git tag [name]

删除版本:$ git tag -d [name]

查看远程版本:$ git tag -r

创建远程版本(本地版本 push 到远程):$ git push origin [name]

删除远程版本:$ git push origin :refs/tags/[name]

合并远程仓库的 tag 到本地:$ git pull origin –tags

上传本地 tag 到远程仓库:$ git push origin –tags

创建带注释的 tag:$ git tag -a [name] -m ‘yourMessage’

4) 子模块(submodule)相关操作命令

添加子模块:$ git submodule add [url] [path]

如:$git submodule add git://github.com/soberh/ui-libs.git src/main/webapp/ui-libs

初始化子模块:$ git submodule init —-只在首次检出仓库时运行一次就行

更新子模块:$ git submodule update —-每次更新或切换分支后都需要运行一下

删除子模块:(分 4 步走)

  1. $ git rm –cached [path]

  2. 编辑“.gitmodules”文件,将子模块的相关配置节点删除掉

  3. 编辑“ .git/config”文件,将子模块的相关配置节点删除掉

  4. 手动删除子模块残留的目录

5)忽略一些文件、文件夹不提交

在仓库根目录下创建名称为“.gitignore”的文件,写入不需要的文件夹名或文件,每个元素占一行即可,如

target

bin

*.db

Git 常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
git branch 查看本地所有分支
git status 查看当前状态
git commit 提交
git branch -a 查看所有的分支
git branch -r 查看本地所有分支
git commit -am "init" 提交并且加注释
git remote add origin git@192.168.1.119:ndshow
git push origin master 将文件给推到服务器上
git remote show origin 显示远程库origin里的资源
git push origin master:develop
git push origin master:hb-dev 将本地库与服务器上的库进行关联
git checkout --track origin/dev 切换到远程dev分支
git branch -D master develop 删除本地库develop
git checkout -b dev 建立一个新的本地分支dev
git merge origin/dev 将分支dev与当前分支进行合并
git checkout dev 切换到本地dev分支
git remote show 查看远程库
git add .
git rm 文件名(包括路径) 从git中删除指定文件
git clone git://github.com/schacon/grit.git 从服务器上将代码给拉下来
git config --list 看所有用户
git ls-files 看已经被提交的
git rm [file name] 删除一个文件
git commit -a 提交当前repos的所有的改变
git add [file name] 添加一个文件到git index
git commit -v 当你用-v参数的时候可以看commit的差异
git commit -m "This is the message describing the commit" 添加commit信息
git commit -a -a是代表add,把所有的change加到git index里然后再commit
git commit -a -v 一般提交命令
git log 看你commit的日志
git diff 查看尚未暂存的更新
git rm a.a 移除文件(从暂存区和工作区中删除)
git rm --cached a.a 移除文件(只从暂存区中删除)
git commit -m "remove" 移除文件(从Git中删除)
git rm -f a.a 强行移除修改后文件(从暂存区和工作区中删除)
git diff --cached 或 $ git diff --staged 查看尚未提交的更新
git stash push 将文件给push到一个临时空间中
git stash pop 将文件从临时空间pop下来
---------------------------------------------------------
git remote add origin git@github.com:username/Hello-World.git
git push origin master 将本地项目给提交到服务器中
-----------------------------------------------------------
git pull 本地与服务器端同步
-----------------------------------------------------------------
git push (远程仓库名) (分支名) 将本地分支推送到服务器上去。
git push origin serverfix:awesomebranch
------------------------------------------------------------------
git fetch 相当于是从远程获取最新版本到本地,不会自动merge
git commit -a -m "log_message" (-a是提交所有改动,-m是加入log信息) 本地修改同步至服务器端 :
git branch branch_0.1 master 从主分支master创建branch_0.1分支
git branch -m branch_0.1 branch_1.0 将branch_0.1重命名为branch_1.0
git checkout branch_1.0/master 切换到branch_1.0/master分支
du -hs

-----------------------------------------------------------
mkdir WebApp
cd WebApp
git init
touch README
git add README
git commit -m 'first commit'
git remote add origin git@github.com:daixu/WebApp.git
git push -u origin master

Git 常用命令图表

image

1、连接 Mysql

格式: mysql -h 主机地址 -u 用户名 -p 用户密码

1、连接到本机上的 MYSQL。
首先打开 DOS 窗口,然后进入目录 mysql\bin,再键入命令 mysql -u root -p,回车后提示你输密码.注意用户名前可以有空格也可以没有空格,但是密码前必须没有空格,否则让你重新输入密码。

如果刚安装好 MYSQL,超级用户 root 是没有密码的,故直接回车即可进入到 MYSQL 中了,MYSQL 的提示符是: mysql>

2、连接到远程主机上的 MYSQL。假设远程主机的 IP 为:110.110.110.110,用户名为 root,密码为 abcd123。则键入以下命令:
mysql -h110.110.110.110 -u root -p 123;(注:u 与 root 之间可以不用加空格,其它也一样)

3、退出 MYSQL 命令: exit (回车)

2、修改密码

格式:mysqladmin -u 用户名 -p 旧密码 password 新密码

1、给 root 加个密码 ab12。
首先在 DOS 下进入目录 mysql\bin,然后键入以下命令
mysqladmin -u root -password ab12
注:因为开始时 root 没有密码,所以-p 旧密码一项就可以省略了。

2、再将 root 的密码改为 djg345。
mysqladmin -u root -p ab12 password djg345

3、增加新用户

注意:和上面不同,下面的因为是 MYSQL 环境中的命令,所以后面都带一个分号作为命令结束符

格式:grant select on 数据库.* to 用户名@登录主机 identified by “密码”

1、增加一个用户 test1 密码为 abc,让他可以在任何主机上登录,并对所有数据库有查询、插入、修改、删除的权限。首先用 root 用户连入 MYSQL,然后键入以下命令

grant select,insert,update,delete on *.* to [email=test1@”%]test1@”%[/email]” Identified by “abc”;

但增加的用户是十分危险的,你想如某个人知道 test1 的密码,那么他就可以在 internet 上的任何一台电脑上登录你的 mysql 数据库并对你的数据可以为所欲为了,解决办法见 2。

2、增加一个用户 test2 密码为 abc,让他只可以在 localhost 上登录,并可以对数据库 mydb 进行查询、插入、修改、删除的操作(localhost 指本地主机,即 MYSQL 数据库所在的那台主机),这样用户即使用知道 test2 的密码,他也无法从 internet 上直接访问数据库,只能通过 MYSQL 主机上的 web 页来访问了。

grant select,insert,update,delete on mydb.* to [email=test2@localhost]test2@localhost[/email] identified by “abc”;

如果你不想 test2 有密码,可以再打一个命令将密码消掉。

grant select,insert,update,delete on mydb.* to [email=test2@localhost]test2@localhost[/email] identified by “”;

4. 数据库操作

4.1 创建数据库

注意:创建数据库之前要先连接 Mysql 服务器

命令:create database <数据库名>

例 1:建立一个名为 xhkdb 的数据库
mysql> create database xhkdb;

例 2:创建数据库并分配用户

①CREATE DATABASE 数据库名;

②GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,ALTER ON 数据库名.* TO 数据库名@localhost IDENTIFIED BY ‘密码’;

③SET PASSWORD FOR ‘数据库名‘@’localhost’ = OLD_PASSWORD(‘密码’);

依次执行 3 个命令完成数据库创建。注意:中文 “密码”和“数据库”是户自己需要设置的。

4.2 显示数据库

命令:show databases (注意:最后有个 s)
mysql> show databases;

注意:为了不再显示的时候乱码,要修改数据库默认编码。以下以 GBK 编码页面为例进行说明:

1、修改 MYSQL 的配置文件:my.ini 里面修改 default-character-set=gbk

2、代码运行时修改

1
2
3
4
5
①Java代码:jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=gbk

②PHP代码:header("Content-Type:text/html;charset=gb2312");

③C语言代码:int mysql_set_character_set( MYSQL * mysql, char * csname);

该函数用于为当前连接设置默认的字符集。字符串 csname 指定了 1 个有效的字符集名称。连接校对成为字符集的默认校对。该函数的工作方式与 SET NAMES 语句类似,但它还能设置

mysql- > charset 的值,从而影响了由 mysql_real_escape_string() 设置的字符集。

4.3 删除数据库

命令:drop database <数据库名>
例如:删除名为 xhkdb 的数据库
mysql> drop database xhkdb;

例子 1:删除一个已经确定存在的数据库
mysql> drop database drop_database;
Query OK, 0 rows affected (0.00 sec)

例子 2:删除一个不确定存在的数据库
mysql> drop database drop_database;
ERROR 1008 (HY000): Can’t drop database ‘drop_database’; database doesn’t exist
//发生错误,不能删除’drop_database’数据库,该数据库不存在。

mysql> drop database if exists drop_database;
Query OK, 0 rows affected, 1 warning (0.00 sec)//产生一个警告说明此数据库不存在

mysql> create database drop_database;
Query OK, 1 row affected (0.00 sec)

mysql> drop database if exists drop_database;//if exists
判断数据库是否存在,不存在也不产生错误 Query OK, 0 rows affected (0.00 sec)

4.4 连接数据库

命令: use <数据库名>

例如:如果 xhkdb 数据库存在,尝试存取它:
mysql> use xhkdb;
屏幕提示:Database changed

use 语句可以通告 MySQL 把 db_name 数据库作为默认(当前)数据库使用,用于后续语句。
该数据库保持为默认数据库,直到语段的结尾,或者直到发布一个不同的 USE 语句:

1
2
3
4
mysql> USE db1;
mysql> SELECT COUNT(*) FROM mytable; # selects from db1.mytable
mysql> USE db2;
mysql> SELECT COUNT(*) FROM mytable; # selects from db2.mytable

使用 USE 语句为一个特定的当前的数据库做标记,不会阻碍您访问其它数据库中的表。下面的例子可以从 db1 数据库访问作者表,并从 db2 数据库访问编辑表:

1
2
3
mysql> USE db1;
mysql> SELECT author_name,editor_name FROM author,db2.editor
-> WHERE author.editor_id = db2.editor.editor_id;

USE 语句被设立出来,用于与 Sybase 相兼容。

有些网友问到,连接以后怎么退出。其实,不用退出来,use 数据库后,使用 show databases 就能查询所有数据库,如果想跳到其他数据库,用
use 其他数据库名字
就可以了。

4.5 当前选择的数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
命令:mysql> select database();

MySQL中SELECT命令类似于其他编程语言里的print或者write,你可以用它来显示一个字符串、数字、数学表达式的结果等等。如何使用MySQL中SELECT命令的特殊功能?

1.显示MYSQL的版本
mysql> select version();
+-----------------------+
| version() |
+-----------------------+
| 6.0.4-alpha-community |
+-----------------------+
1 row in set (0.02 sec)

2. 显示当前时间
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2009-09-15 22:35:32 |
+---------------------+
1 row in set (0.04 sec)

3. 显示年月日
SELECT DAYOFMONTH(CURRENT_DATE);
+--------------------------+
| DAYOFMONTH(CURRENT_DATE) |
+--------------------------+
| 15 |
+--------------------------+
1 row in set (0.01 sec)

SELECT MONTH(CURRENT_DATE);
+---------------------+
| MONTH(CURRENT_DATE) |
+---------------------+
| 9 |
+---------------------+
1 row in set (0.00 sec)

SELECT YEAR(CURRENT_DATE);
+--------------------+
| YEAR(CURRENT_DATE) |
+--------------------+
| 2009 |
+--------------------+
1 row in set (0.00 sec)

4. 显示字符串
mysql> SELECT "welecome to my blog!";
+----------------------+
| welecome to my blog! |
+----------------------+
| welecome to my blog! |
+----------------------+
1 row in set (0.00 sec)

5. 当计算器用
select ((4 * 4) / 10 ) + 25;
+----------------------+
| ((4 * 4) / 10 ) + 25 |
+----------------------+
| 26.60 |
+----------------------+
1 row in set (0.00 sec)

6. 串接字符串
select CONCAT(f_name, " ", l_name)
AS Name
from employee_data
where title = 'Marketing Executive';
+---------------+
| Name |
+---------------+
| Monica Sehgal |
| Hal Simlai |
| Joseph Irvine |
+---------------+
3 rows in set (0.00 sec)
注意:这里用到CONCAT()函数,用来把字符串串接起来。另外,我们还用到以前学到的AS给结果列'CONCAT(f_name, " ", l_name)'起了个假名。

5. 数据表操作

5.1 创建数据表

命令:create table <表名> ( <字段名 1> <类型 1> [,..<字段名 n> <类型 n>]);

例如,建立一个名为 MyClass 的表,

字段名 数据类型 数据宽度 是否为空 是否主键 自动增加 默认值
id int 4 primary key auto_increment
name char 20
sex int 4 0
degree double 16
1
2
3
4
5
mysql> create table MyClass(
> id int(4) not null primary key auto_increment,
> name char(20) not null,
> sex int(4) not null default '0',
> degree double(16,2));

5.2 删除数据表

命令:drop table <表名>

例如:删除表名为 MyClass 的表

mysql> drop table MyClass;

DROP TABLE 用于取消一个或多个表。您必须有每个表的 DROP 权限。所有的表数据和表定义会被取消,所以使用本语句要小心!

注意:对于一个带分区的表,DROP TABLE 会永久性地取消表定义,取消各分区,并取消储存在这些分区中的所有数据。DROP TABLE 还会取消与被取消的表有关联的分区定义(.par)文件。

对于不存在的表,使用 IF EXISTS 用于防止错误发生。当使用 IF EXISTS 时,对于每个不存在的表,会生成一个 NOTE。

RESTRICT 和 CASCADE 可以使分区更容易。目前,RESTRICT 和 CASCADE 不起作用。

5.3 表插入数据

命令:insert into <表名> [( <字段名 1>[,..<字段名 n > ])] values ( 值 1 )[, ( 值 n )]

例如:往表 MyClass 中插入二条记录, 这二条记录表示:编号为 1 的名为 Tom 的成绩为 96.45, 编号为 2 的名为 Joan 的成绩为 82.99, 编号为 3 的名为 Wang 的成绩为 96.5。
mysql> insert into MyClass values(1,’Tom’,96.45),(2,’Joan’,82.99), (2,’Wang’, 96.59);

注意:insert into 每次只能向表中插入一条记录

5.4 查询表中的数据

1)、查询所有行
命令: select <字段 1,字段 2,…> from < 表名 > where < 表达式 >
例如:查看表 MyClass 中所有数据
mysql> select * from MyClass;

2)、查询前几行数据
例如:查看表 MyClass 中前 2 行数据
mysql> select * from MyClass order by id limit 0,2;

select 一般配合 where 使用,以查询更精确更复杂的数据。

5.5 删除表中数据

命令:delete from 表名 where 表达式

例如:删除表 MyClass 中编号为 1 的记录

mysql> delete from MyClass where id=1;

下面是一个删除数据前后表的对比。

FirstName LastName Age
Peter Griffin 35
Glenn Quagmire 33

下面以 PHP 代码为例删除 “Persons” 表中所有 LastName=’Griffin’ 的记录:

1
2
3
4
5
6
7
8
9
<?php
$con = mysql_connect("localhost","peter","abc123");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("my_db", $con);
mysql_query("DELETE FROM Persons WHERE LastName='Griffin'"); mysql_close($con);
?>

在这次删除之后,表是这样的:

FirstName LastName Age
Glenn Quagmire 33

5.6 修改表中数据

语法:update 表名 set 字段=新值,… where 条件
mysql> update MyClass set name=’Mary’ where id=1;

例子 1:单表的 MySQL UPDATE 语句:

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name SET col_name1=expr1 [, col_name2=expr2 …] [WHERE where_definition] [ORDER BY …] [LIMIT row_count]

例子 2:多表的 UPDATE 语句:

UPDATE [LOW_PRIORITY] [IGNORE] table_references SET col_name1=expr1 [, col_name2=expr2 …] [WHERE where_definition]

UPDATE 语法可以用新值更新原有表行中的各列。SET 子句指示要修改哪些列和要给予哪些值。WHERE 子句指定应更新哪些行。如果没有 WHERE 子句,则更新所有的行。如果指定了 ORDER BY 子句,则按照被指定的顺序对行进行更新。LIMIT 子句用于给定一个限值,限制可以被更新的行的数目。

5.7 增加字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
命令:alter table 表名 add字段 类型 其他;
例如:在表MyClass中添加了一个字段passtest,类型为int(4),默认值为0
mysql> alter table MyClass add passtest int(4) default '0'

加索引
mysql> alter table 表名 add index 索引名 (字段名1[,字段名2 …]);
例子: mysql> alter table employee add index emp_name (name);

加主关键字的索引
mysql> alter table 表名 add primary key (字段名);
例子: mysql> alter table employee add primary key(id);

加唯一限制条件的索引
mysql> alter table 表名 add unique 索引名 (字段名);
例子: mysql> alter table employee add unique emp_name2(cardnumber);

删除某个索引
mysql> alter table 表名 drop index 索引名;
例子: mysql>alter table employee drop index emp_name;

增加字段:
mysql> ALTER TABLE table_name ADD field_name field_type;

修改原字段名称及类型:
mysql> ALTER TABLE table_name CHANGE old_field_name new_field_name field_type;

删除字段:
MySQL ALTER TABLE table_name DROP field_name;

5.8 修改表名

命令:rename table 原表名 to 新表名;

例如:在表 MyClass 名字更改为 YouClass
mysql> rename table MyClass to YouClass;

当你执行 RENAME 时,你不能有任何锁定的表或活动的事务。你同样也必须有对原初表的 ALTER 和 DROP 权限,以及对新表的 CREATE 和 INSERT 权限。

如果在多表更名中,MySQL 遭遇到任何错误,它将对所有被更名的表进行倒退更名,将每件事物退回到最初状态。

RENAME TABLE 在 MySQL 3.23.23 中被加入。

6、备份数据库

命令在 DOS 的[url=file://\mysql\bin]\mysql\bin[/url]目录下执行

1.导出整个数据库
导出文件默认是存在 mysql\bin 目录下
mysqldump -u 用户名 -p 数据库名 > 导出的文件名
mysqldump -u user_name -p123456 database_name > outfile_name.sql

2.导出一个表
mysqldump -u 用户名 -p 数据库名 表名> 导出的文件名
mysqldump -u user_name -p database_name table_name > outfile_name.sql

3.导出一个数据库结构
mysqldump -u user_name -p -d –add-drop-table database_name > outfile_name.sql
-d 没有数据 –add-drop-table 在每个 create 语句之前增加一个 drop table

4.带语言参数导出
mysqldump -uroot -p –default-character-set=latin1 –set-charset=gbk –skip-opt database_name > outfile_name.sql

例如,将 aaa 库备份到文件 back_aaa 中:
  [root@test1 root]# cd  /home/data/mysql
  [root@test1 mysql]# mysqldump -u root -p –opt aaa > back_aaa

7. 实例

7.1 一个建库和建表的实例 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
drop database if exists school; //如果存在SCHOOL则删除
create database school; //建立库SCHOOL
use school; //打开库SCHOOL
create table teacher //建立表TEACHER
(
id int(3) auto_increment not null primary key,
name char(10) not null,
address varchar(50) default ‘深圳’,
year date
); //建表结束

//以下为插入字段
insert into teacher values(”,’allen’,'大连一中’,'1976-10-10′);
insert into teacher values(”,’jack’,'大连二中’,'1975-12-23′);

如果你在mysql提示符键入上面的命令也可以,但不方便调试。
1、你可以将以上命令原样写入一个文本文件中,假设为school.sql,然后复制到c:\\下,并在DOS状态进入目录[url=file://\\mysql\\bin]\\mysql\\bin[/url],然后键入以下命令:
mysql -uroot -p密码 < c:\\school.sql
如果成功,空出一行无任何显示;如有错误,会有提示。(以上命令已经调试,你只要将//的注释去掉即可使用)。

2、或者进入命令行后使用 mysql> source c:\\school.sql; 也可以将school.sql文件导入数据库中。

7.2 一个建库和建表的实例 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
drop database if exists school; //如果存在SCHOOL则删除
create database school; //建立库SCHOOL
use school; //打开库SCHOOL
create table teacher //建立表TEACHER
(
id int(3) auto_increment not null primary key,
name char(10) not null,
address varchar(50) default ''深圳'',
year date
); //建表结束

//以下为插入字段
insert into teacher values('''',''glchengang'',''深圳一中'',''1976-10-10'');
insert into teacher values('''',''jack'',''深圳一中'',''1975-12-23'');

注:在建表中

1、将 ID 设为长度为 3 的数字字段:int(3);并让它每个记录自动加一:auto_increment;并不能为空:not null;而且让他成为主字段 primary key。

2、将 NAME 设为长度为 10 的字符字段

3、将 ADDRESS 设为长度 50 的字符字段,而且缺省值为深圳。

4、将 YEAR 设为日期字段。

8、Mysql 语句记录

1
2
3
use mysql;
set password for 'root'@'localhost'=password('123456');
flush privileges;

Scss 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能,这些拓展令 CSS 更加强大与优雅。

1. 使用变量

因为 css 里不能使用变量,造成很大不便。所以 scss 里引入了变量。

任何可以用作 css 属性值的赋值都可以用作 scss 的变量值,甚至是以空格分割的多个属性值。

1
2
3
4
5
$width: 100px; // 定义$width变量
nav {
width: $width; // 引用$width变量
color: $nav-color;
}

2. 嵌套 CSS 规则

css 中重复写选择器是非常麻烦的。比如下面这样:

1
2
3
#content article h1 { color: #333 }
#content article p { margin-bottom: 1.4em }
#content aside { background-color: #EEE }

像这种情况,scss 可以只写一遍,且使样式可读性更高。

1
2
3
4
5
6
7
#content {
article {
h1 { color: #333 }
p { margin-bottom: 1.4em }
}
aside { background-color: #EEE }
}

2-1. 父选择器的标识符&

当你想为 article 元素内 a 标签写 :hover 这种伪类时,css 的写法是:

1
2
3
4
5
6
article a {
color: blue;
}
article a:hover {
color: red;
}

而 scss 可以通过&符号实现上面功能,更方便也更容易理解

1
2
3
4
article a {
color: blue;
&:hover { color: red }
}

常用父选择器用法:

&:hover

&:active

&:disabled

&:focus

&::placeholder

&::after

2-2. 群组选择器的嵌套

你需要在一个特定的容器元素内对一个群组选择器进行修饰时。css 的写法是让你在群组选择器中的每一个选择器前都重复一遍容器元素的选择器。

1
.container h1, .container h2, .container h3 { margin-bottom: .8em }

而用 scss 写是这样的

1
2
3
.container {
h1, h2, h3 {margin-bottom: .8em}
}

有利必有弊,你需要特别注意群组选择器的规则嵌套生成的 css。虽然 scss 让你的样式表看上去很小,但实际生成的 css 却可能非常大,这会降低网站的速度。

2-3. 子组合选择器和同层组合选择器:>、+和~

上边这三个组合选择器必须和其他选择器配合使用,以指定浏览器仅选择某种特定上下文中的元素。

用子组合选择器 > 选择一个元素的直接子元素。选择器会选择 article 下紧跟着的 section 子元素。

1
article > section { border: 1px solid #ccc }

用同层相邻组合选择器 + 选择 header 元素后紧跟的 p 元素

1
header + p { font-size: 1.1em }

你也可以用同层全体组合选择器~,选择所有跟在 article 后的同层 article 元素,不管它们之间隔了多少其他元素

1
article ~ article { border-top: 1px dashed #ccc }

3. 注释 /* */ 与 //

Scss 支持标准的 CSS 多行注释 /* */,以及单行注释 //

4. 混合器

scss 的混合器可以实现大段样式的重用。混合器使用@mixin 标识符定义,然后通过@include 来使用这个混合器。
为便于书写,@mixin 可以用 = 表示,而 @include 可以用 + 表示

1
2
3
4
5
6
@mixin div-back{
background: red;
}
.item {
@include div-back;
}

4-1. 给混合器传参

混合器可以做为方法一样可以传参

1
2
3
4
5
6
@mixin div-back($color) {
background: $color;
}
.item {
@include div-back(red);
}

当你用混合器传参时,有时候会很难区分每个参数是什么意思,参数之间是一个什么样的顺序。为了解决这个问题,scss 允许通过语法$name: value 的形式指定每个参数的值

1
2
3
4
5
6
7
8
9
10
@mixin div-back($color,$size) {
background: $color;
font-size: $size;
}
.item {
@include div-back(
$color: green,
$size: 30px
);
}

为了在@include 混合器时不必传入所有的参数,我们可以给参数指定一个默认值。

1
2
3
4
5
6
7
8
9
@mixin div-back($color,$size: 20px) {
background: $color;
font-size: $size;
}
.item {
@include div-back(
$color: green
);
}

5. 继承

使用 scss 的时候,最后一个减少重复的主要特性就是选择器继承。选择器继承是说一个选择器可以继承为另一个选择器定义的所有样式。这个通过@extend 语法实现。

1
2
3
4
5
6
7
.div {
font-size: 40px;
}
.item {
@extend .div;
background: red;
}

6. 占位符选择器 %

有时,需要定义一套样式并不是给某个元素用,而是只通过 @extend 指令使用。当占位符选择器单独使用时(未通过 @extend 调用),不会编译到 CSS 文件中。

1
2
3
4
5
6
7
8
#context a%extreme {
color: blue;
font-weight: bold;
font-size: 2em;
}
.notice {
@extend %extreme;
}

编译为

1
2
3
4
5
#context a.notice {
color: blue;
font-weight: bold;
font-size: 2em;
}

原理可以理解为用@extend 的.notice 去替换占位符选择器%extreme 的位置。

7. ScssScript

ScssScript 支持 6 种主要的数据类型:

  • 数字:1, 2, 13, 10px
  • 字符串:有引号字符串与无引号字符串,”foo”, ‘bar’, baz
  • 颜色:blue, #04a3f9, rgba(255,0,0,0.5)
  • 布尔型:true, false
  • 空值:null
  • 数组 (list):用空格或逗号作分隔符,1.5em 1em 0 2em, Helvetica, Arial, sans-serif
  • maps:相当于 JavaScript 的 object,(key1: value1, key2: value2)
1
2
3
4
5
6
@mixin firefox-message($selector) {
body.firefox #{$selector}:before {
content: "Hi, Firefox users!";
}
}
@include firefox-message(".header");

编译为

1
2
3
body.firefox .header:before {
content: "Hi, Firefox users!";
}

所有数据类型均支持相等运算 == 或 !=,此外,每种数据类型也有其各自支持的运算方式。

7-1. 颜色值运算

颜色值的运算是分段计算进行的,也就是分别计算红色,绿色,以及蓝色的值:

1
2
3
p {
color: #010203 + #040506;
}

计算 01 + 04 = 05 02 + 05 = 07 03 + 06 = 09,然后编译为

1
2
3
p {
color: #050709;
}
  • 可用于连接字符串
1
2
3
.item {
background: re + d;
}

在有引号的文本字符串中使用 #{} 插值语句可以添加动态的值:

1
2
3
p:before {
content: "I ate #{5 + 10} pies!";
}

7-2. 变量定义 !default

可以在变量的结尾添加 !default 给一个未通过 !default 声明赋值的变量赋值,此时,如果变量已经被赋值,不会再被重新赋值,但是如果变量还没有被赋值,则会被赋予新的值。

7-3. @if、@for、@each、@while

scss 也可以写 if else 等。

1
2
3
4
5
6
7
8
9
10
11
12
$type: monster;
p {
@if $type == ocean {
color: blue;
} @else if $type == matador {
color: red;
} @else if $type == monster {
color: green;
} @else {
color: black;
}
}

编译为

1
2
3
p {
color: green;
}

8. 函数指令

Sass 支持自定义函数,并能在任何属性值或 Sass script 中使用:

1
2
3
4
5
6
7
8
$grid-width: 40px;
$gutter-width: 10px;

@function grid-width($n) {
@return $n * $grid-width + ($n - 1) * $gutter-width;
}

#sidebar { width: grid-width(5); }

编译为

1
2
3
#sidebar {
width: 240px;
}

一,介绍与需求分析

1.1,介绍

dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,所以 dva 是基于现有应用架构 (redux + react-router + redux-saga 等)的一层轻量封装。是由阿里架构师 sorrycc 带领 team 完成的一套前端框架。

1.2,需求

快速搭建基于 react 的项目(PC 端,移动端)。

二,DvaJS 构建项目

2.1,初始化项目

第一步:安装 node

第二步:安装最新版本 dva-cli

1
2
1 $ npm install dva-cli -g
2 $ dva -v

第三步:dva new 创建新应用

1
1 $ dva new myapp

也可以在创建项目目录 myapp 后,用 dva init 初始化项目

1
1 $ dva init

第四步:运行项目

1
2
1 $ cd myapp
2 $ npm start

浏览器会自动打开一个窗口

image

2.2,项目架构介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|-mock             //存放用于 mock 数据的文件
|-node_modules //项目包
|-public //一般用于存放静态文件,打包时会被直接复制到输出目录(./dist)
|-src //项目源代码
| |-assets //用于存放静态资源,打包时会经过 webpack 处理
| |-caches //缓存
| |-components //组件 存放 React 组件,一般是该项目公用的无状态组件
| |-entries //入口
| |-models //数据模型 存放模型文件
| |-pages //页面视图
| |-routes //路由 存放需要 connect model 的路由组件
| |-services //服务 存放服务文件,一般是网络请求等
| |-test //测试
| |-utils //辅助工具 工具类库
|-package.json //包管理代码
|-webpackrc.js //开发配置
|-tsconfig.json /// ts配置
|-webpack.config.js //webpack配置
|-.gitignore //Git忽略文件
在dva项目目录中主要分3层,models,services,components,其中models是最重要概念,这里放的是各种数据,与数据交互的应该都是在这里。services是请求后台接口的方法。components是组件了。

三,DvaJS 的使用

3.1,DvaJS 的五个 Api

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import dva from 'dva';
import {message} from 'antd';
import './index.css';

// 1. Initialize 创建 dva 应用实例
const app = dva();

// 2. Plugins 装载插件(可选)
app.use({
onError: function (error, action) {
message.error(error.message || '失败', 5);
}
});

// 3. Model 注册model
app.model(require('../models/example').default);

// 4. Router 配置路由
app.router(require('../routes/router').default);

// 5. Start 启动应用
app.start('#root');

export default app._store; // eslint-disable-line 抛出

1,app = dva(Opts):创建应用,返回 dva 实例。(注:dva 支持多实例)

在 opts 可以配置所有的 hooks

1
2
3
4
5
6
const app = dva({
history,
initialState,
onError,
onHmr,
});

这里比较常用的是,history 的配置,一般默认的是 hashHistory,如果要配置 history 为 browserHistory,可以这样:

1
2
3
4
5
1 import dva from 'dva';
2 import createHistory from 'history/createBrowserHistory';
3 const app = dva({
4 history: createHistory(),
5 });
  • initialState:指定初始数据,优先级高于 model 中的 state,默认是 {},但是基本上都在 modal 里面设置相应的 state

2,app.use(Hooks):配置 hooks 或者注册插件。

1
2
3
4
5
1 app.use({
2 onError: function (error, action) {
3 message.error(error.message || '失败', 5);
4 }
5 });

可以根据自己的需要来选择注册相应的插件

3,app.model(ModelObject):这里是数据逻辑处理,数据流动的地方。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
export default {

namespace: 'example',//model 的命名空间,同时也是他在全局 state 上的属性,只能用字符串,我们在发送 action 到相应的 reducer 时,就会需要用到 namespace

state: {},//表示 Model 的状态数据,通常表现为一个 javascript 对象(当然它可以是任何值)

subscriptions: {//语义是订阅,用于订阅一个数据源,然后根据条件 dispatch 需要的 action
setup({ dispatch, history }) { // eslint-disable-line
},
},

effects: {//Effect 被称为副作用,最常见的就是异步操作
*fetch({ payload }, { call, put }) { // eslint-disable-line
yield put({ type: 'save' });
},
},

reducers: {//reducers 聚合积累的结果是当前 model 的 state 对象
save(state, action) {
return { ...state, ...action.payload };
},
},

};

4,app.router(Function):注册路由表,我们做路由跳转的地方

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import React from 'react';
import { routerRedux, Route ,Switch} from 'dva/router';
import { LocaleProvider } from 'antd';
import App from '../components/App/App';
import Flex from '../components/Header/index';
import Login from '../pages/Login/Login';
import Home from '../pages/Home/Home';
import zhCN from 'antd/lib/locale-provider/zh_CN';
const {ConnectedRouter} = routerRedux;

function RouterConfig({history}) {
return (
<ConnectedRouter history={history}>
<Switch>
<Route path="/login" component={Login} />
<LocaleProvider locale={zhCN}>
<App>
<Flex>
<Switch>
<Route path="/" exact component={Home} />
</Switch>
</Flex>
</App>
</LocaleProvider>
</Switch>
</ConnectedRouter>
);
}

export default RouterConfig;

5,app.start([HTMLElement], opts)
启动我们自己的应用

3.2,DvaJS 的十个概念

1,Model

model 是 dva 中最重要的概念,Model 非 MVC 中的 M,而是领域模型,用于把数据相关的逻辑聚合到一起,几乎所有的数据,逻辑都在这边进行处理分发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import Model from 'dva-model';
// import effect from 'dva-model/effect';
import queryString from 'query-string';
import pathToRegexp from 'path-to-regexp';
import {ManagementPage as namespace} from '../../utils/namespace';
import {
getPages,
} from '../../services/page';

export default Model({
namespace,
subscriptions: {
setup({dispatch, history}) { // eslint-disable-line
history.listen(location => {
const {pathname, search} = location;
const query = queryString.parse(search);
const match = pathToRegexp(namespace + '/:action').exec(pathname);
if (match) {
dispatch({
type:'getPages',
payload:{
s:query.s || 10,
p:query.p || 1,
j_code:parseInt(query.j,10) || 1,
}
});
}

})
}
},
reducers: {
getPagesSuccess(state, action) {
const {list, total} = action.result;
return {...state, list, loading: false, total};
},
}
}, {
getPages,
})

2,namespace

model 的命名空间,同时也是他在全局 state 上的属性,只能用字符串,我们在发送 action 到相应的 reducer 时,就会需要用到 namespace

3,State(状态)

初始值,我们在 dva() 初始化的时候和在 modal 里面的 state 对其两处进行定义,其中 modal 中的优先级低于传给 dva() 的 opts.initialState

1
2
3
4
5
6
7
8
9
10
// dva()初始化
const app = dva({
initialState: { count: 1 },
});

// modal()定义事件
app.model({
namespace: 'count',
state: 0,
});

Model 中 state 的优先级比初始化的低,但是基本上项目中的 state 都是在这里定义的

4,Subscription

Subscriptions 是一种从 源 获取数据的方法,它来自于 elm。语义是订阅,用于订阅一个数据源,然后根据条件 dispatch 需要的 action。数据源可以是当前的时间、服务器的 websocket 连接、keyboard 输入、geolocation 变化、history 路由变化等等

1
2
3
4
5
6
7
8
9
10
11
12
13
subscriptions: { //触发器。setup表示初始化即调用。
setup({dispatch, history}) {
history.listen(location => {//listen监听路由变化 调用不同的方法
if (location.pathname === '/login') {
//清除缓存
} else {
dispatch({
type: 'fetch'
});
}
});
},
},

5,Effects

用于处理异步操作和业务逻辑,不直接修改 state,简单的来说,就是从服务端获取数据,并且发起一个 action 交给 reducer 的地方。其中它用到了 redux-saga 里面几个常用的函数。

  • put 用来发起一条 action
  • call 以异步的方式调用函数
  • select 从 state 中获取相关的数据
  • take 获取发送的数据
1
2
3
4
5
6
7
8
9
10
11
12
effects: {
*login(action, saga){
const data = yield saga.call(effect(login, 'loginSuccess', authCache), action, saga);//call 用户调用异步逻辑 支持Promise
if (data && data.token) {
yield saga.put(routerRedux.replace('/home'));//put 用于触发action 什么是action下面会讲到
}
},
*logout(action, saga){
const state = yield saga.select(state => state);//select 从state里获取数据
},

},

如果 effect 与 reducers 中的 add 方法重合了,这里会陷入一个死循环,因为当组件发送一个 dispatch 的时候,model 会首先去找 effect 里面的方法,当又找到 add 的时候,就又会去请求 effect 里面的方法。

这里的 delayDeal,是我这边写的一个延时的函数,我们在 utils 里面编写一个 utils.js

1
2
3
4
5
6
7
8
9
10
/**
*超时函数处理
* @param timeout :timeout超时的时间参数
* @returns {*} :返回样式值
*/
export function delayDeal(timeout) {
return new Promise((resolve) => {
setTimeout(resolve, timeout);
});
}

接着我们在 models/example.js 导入这个 utils.js

1
1 import { delayDeal} from '../utils/utils';

6,Reducer

以 key/value 格式定义 reducer,用于处理同步操作,唯一可以修改 state 的地方。由 action 触发。其实是一个纯函数。

1
2
3
4
5
1  reducers: {
2 loginSuccess(state, action){
3 return {...state, auth: action.result, loading: false};
4 },
5 }

7,Router

Router 表示路由配置信息,项目中的 router.js

8,RouteComponent

RouteComponent 表示 Router 里匹配路径的 Component,通常会绑定 model 的数据

9,Action:表示操作事件,可以是同步,也可以是异步

action 的格式如下,它需要有一个 type ,表示这个 action 要触发什么操作;payload 则表示这个 action 将要传递的数据

1
2
3
4
5
6
7
{
type: namespace + '/login',
payload: {
userName: payload.userName,
password: payload.password
}
}

构建一个 Action 创建函数,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
function goLogin(payload) {
let loginInfo = {
type: namespace + '/login',
payload: {
userName: payload.userName,
password: payload.password
}
}
return loginInfo
}

//我们直接dispatch(goLogin()),就发送了一个action。
dispatch(goLogin())

10,dispatch

type dispatch = (a: Action) => Action

dispatching function 是一个用于触发 action 的函数,action 是改变 State 的唯一途径,但是它只描述了一个行为,而 dipatch 可以看作是触发这个行为的方式,而 Reducer 则是描述如何改变数据的。

在 dva 中,connect Model 的组件通过 props 可以访问到 dispatch,可以调用 Model 中的 Reducer 或者 Effects,常见的形式如:

1
2
3
4
1 dispatch({
2 type: namespace + '/login', // 如果在 model 外调用,需要添加 namespace,如果在model内调用 无需添加 namespace
3 payload: {}, // 需要传递的信息
4 });

3.3,使用 antd

先安装 antd 和 babel-plugin-import

1
2
3
1 npm install antd babel-plugin-import --save
2 # 或
3 yarn add antd babel-plugin-import

babel-plugin-import 也可以通过 -D 参数安装到 devDependencies 中,它用于实现按需加载。然后在 .webpackrc 中添加如下配置:

1
2
3
4
5
6
7
8
9
{
"extraBabelPlugins": [
["import", {
"libraryName": "antd",
"libraryDirectory": "es",
"style": true
}]
]
}

现在就可以按需引入 antd 的组件了,如 import { Button } from ‘antd’,Button 组件的样式文件也会自动帮你引入。

3.4,配置.webpackrc

1,entry 是入口文件配置

单页类型:

1
1 entry: './src/entries/index.js',

多页类型:

1
1 "entry": "src/entries/*.js"

2,extraBabelPlugins 定义额外的 babel plugin 列表,格式为数组。

3,env 针对特定的环境进行配置。dev 的环境变量是 development,build 的环境变量是 production。

1
2
3
4
5
6
7
8
9
10
"extraBabelPlugins": ["transform-runtime"],
"env": {
development: {
extraBabelPlugins: ['dva-hmr'],
},
production: {
define: {
__CDN__: process.env.CDN ? '//cdn.dva.com/' : '/' }
}
}

开发环境下的 extraBabelPlugins 是 [“transform-runtime”, “dva-hmr”],而生产环境下是 [“transform-runtime”]

4,配置 webpack 的 externals 属性

1
2
3
4
5
1 // 配置 @antv/data-set和 rollbar 不打入代码
2 "externals": {
3 '@antv/data-set': 'DataSet',
4 rollbar: 'rollbar',
5 }

5,配置 webpack-dev-server 的 proxy 属性。 如果要代理请求到其他服务器,可以这样配:

1
2
3
4
5
6
7
8
9
proxy: {
"/api": {
// "target": "http://127.0.0.1/",
// "target": "http://127.0.0.1:9090/",
"target": "http://localhost:8080/",
"changeOrigin": true,
"pathRewrite": { "^/api" : "" }
}
},

6,disableDynamicImport

禁用 import() 按需加载,全部打包在一个文件里,通过 babel-plugin-dynamic-import-node-sync 实现。

7,publicPath

配置 webpack 的 output.publicPath 属性。

8,extraBabelIncludes

定义额外需要做 babel 转换的文件匹配列表,格式为数组

9,outputPath

配置 webpack 的 output.path 属性。

打包输出的文件

1
1 config["outputPath"] = path.join(process.cwd(), './build/')

10,根据需求完整配置如下:

文件名称是:.webpackrc.js,可根据实际情况添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
const path = require('path');

const config = {
entry: './src/entries/index.js',
extraBabelPlugins: [['import', { libraryName: 'antd', libraryDirectory: 'es', style: true }]],
env: {
development: {
extraBabelPlugins: ['dva-hmr'],
},
production: {
define: {
__CDN__: process.env.CDN ? '//cdn.dva.com/' : '/' }
}
},
externals: {
'@antv/data-set': 'DataSet',
rollbar: 'rollbar',
},
lessLoaderOptions: {
javascriptEnabled: true,
},
proxy: {
"/api": {
// "target": "http://127.0.0.1/",
// "target": "http://127.0.0.1:9090/",
"target": "http://localhost:8080/",
"changeOrigin": true,
}
},
es5ImcompatibleVersions:true,
disableDynamicImport: true,
publicPath: '/',
hash: false,
extraBabelIncludes:[
"node_modules"
]
};
if (module.exports.env !== 'development') {
config["outputPath"] = path.join(process.cwd(), './build/')
}
export default config

更多 .webpackrc 的配置请参考 roadhog 配置

3.5,使用 antd-mobile

先安装 antd-mobile 和 babel-plugin-import

1
2
1 npm install antd-mobile babel-plugin-import --save # 或
2 yarn add antd-mobile babel-plugin-import

babel-plugin-import 也可以通过 -D 参数安装到 devDependencies 中,它用于实现按需加载。然后在 .webpackrc 中添加如下配置:

1
2
3
4
5
1 {
2 "plugins": [
3 ["import", { libraryName: "antd-mobile", style: "css" }] // `style: true` 会加载 less 文件
4 ]
5 }

现在就可以按需引入 antd-mobile 的组件了,如 import { DatePicker} from ‘antd-mobile’,DatePicker 组件的样式文件也会自动帮你引入。

四,整体架构

  • 我们根据 url 访问相关的 Route-Component,在组件中我们通过 dispatch 发送 action 到 model 里面的 effect 或者直接 Reducer
  • 当我们将 action 发送给 Effect,基本上是取服务器上面请求数据的,服务器返回数据之后,effect 会发送相应的 action 给 reducer,由唯一能改变 state 的 reducer 改变 state ,然后通过 connect 重新渲染组件。
  • 当我们将 action 发送给 reducer,那直接由 reducer 改变 state,然后通过 connect 重新渲染组件。如下图所示:

image

数据流向

数据的改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转等)触发的,当此类行为会改变数据的时候可以通过 dispatch 发起一个 action,如果是同步行为会直接通过 Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变 State

重置 models 里的数据:

1
1 dispatch({type:namespace+'/set',payload:{mdata:[]}});

set 是内置的方法

五,问题记录

5.1,路由相关的问题

1,使用 match 后的路由跳转问题,版本 routerV4

match 是一个匹配路径参数的对象,它有一个属性 params,里面的内容就是路径参数,除常用的 params 属性外,它还有 url、path、isExact 属性。

问题描述:不能跳转新页面或匹配跳转后,刷新时 url 所传的值会被重置掉

不能跳转的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const {ConnectedRouter} = routerRedux;

function RouterConfig({history}) {
const tests =({match}) =>(
<div>
<Route exact path={`${match.url}/:tab`} component={Test}/>
<Route exact path={match.url} component={Test}/>
</div>
);
return (
<ConnectedRouter history={history}>
<Switch>
<Route path="/login" component={Login}/>
<LocaleProvider locale={zhCN}>
<App>
<Flex>
<Switch>
<Route path="/test" component={tests }/>
<Route exact path="/test/bindTest" component={BindTest}/>

</Switch>
</Flex>
</App>
</LocaleProvider>
</Switch>
</ConnectedRouter>
);
}

路由如上写法,使用下面方式不能跳转,但是地址栏路径变了

1
2
3
4
5
6
7
8
9
10
11
12
import { routerRedux} from 'dva/router';
...

this.props.dispatch(routerRedux.push({
pathname: '/test/bindTest',
search:queryString.stringify({
// ...query,
Code: code,
Name: name
})
}));
...

能跳转,但是刷新所传的参数被重置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const {ConnectedRouter} = routerRedux;

function RouterConfig({history}) {
const tests =({match}) =>(
<div>
<Route exact path={`${match.url}/bindTest`} component={BindTest}/>
<Route exact path={`${match.url}/:tab`} component={Test}/>
<Route exact path={match.url} component={Test}/>
</div>
);
return (
<ConnectedRouter history={history}>
<Switch>
<Route path="/login" component={Login}/>
<LocaleProvider locale={zhCN}>
<App>
<Flex>
<Switch>
<Route path="/test" component={tests }/>
</Switch>
</Flex>
</App>
</LocaleProvider>
</Switch>
</ConnectedRouter>
);
}

路由如上写法,使用下面方式可以跳转,但是刷新时所传的参数会被 test 里所传的参数重置

1
2
3
4
5
6
7
8
9
10
11
12
...

this.props.dispatch(routerRedux.push({
pathname: '/test/bindTest',
search:queryString.stringify({
// ...query,
Code: code,
Name: name
})
}));

...

解决办法如下:地址多加一级,跳出以前的界面

路由配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const {ConnectedRouter} = routerRedux;

function RouterConfig({history}) {
const tests =({match}) =>(
<div>
<Route exact path={`${match.url}/bind/test`} component={BindTest}/>
<Route exact path={`${match.url}/:tab`} component={Test}/>
<Route exact path={match.url} component={Test}/>
</div>
);
return (
<ConnectedRouter history={history}>
<Switch>
<Route path="/test" component={tests }/>
</Switch>
</ConnectedRouter>
);
}

调用

1
2
3
4
5
6
7
8
9
10
11
12
...

this.props.dispatch(routerRedux.push({
pathname: '/test/bind/test1',
search:queryString.stringify({
// ...query,
Code: code,
Name: name
})
}));

...

5.2,箭头函数 this 指向问题

箭头函数的 this 定义:箭头函数的 this 是在定义函数时绑定的,不是在执行过程中绑定的。简单的说,函数在定义时,this 就继承了定义函数的对象

1.构建 node 下载环境

在 nodejs 官网下载 node 并且安装 nodejs 在 wind10(推荐下载长期支持版)下载地址:https://nodejs.org/zh-cn/download/current/

完成安装后打开电脑的 cmd 测试 node 环境:

image

出现以上显示表示 node 环境已经构建好了。

2.换淘宝的源提升下载速度

cmd 中输入命令:

1
npm install -g cnpm –registry=https://registry.npm.taobao.org

下载完成后,输入测试命令:

1
cnpm -v

image

出现以上显示表示换源成功,以后在用到 npm 的地方就用 cnpm 就好了,可提升效率

3.搭建 vue 前端框架环境:

在 cmd 中输入命令:

1
cnpm install --global vue-cli

等待下载完成,速度很快,大概 30 秒

image

测试 vue 是否搭建完成:

image

显示版本号即搭建 vue 框架完成(注意 vue 和 cli 与中间的-要有空格)

4.新建 vue 框架项目

1.打开集成环境(我这里用的是 WebStorm)

打开后,点击左下角的 Terminal 进入 cmd 命令框输入命令:

1
vue init webpack element-test

vue init webpack +项目名,我这里用 element-test 为例

image

image

说明:

Vue build ==> 打包方式,回车即可;

Install vue-router ==> 是否要安装 vue-router,项目中肯定要使用到 所以 Y 回车;

Use ESLint to lint your code ==> 是否需要 js 语法检测 目前我们不需要 所以 n 回车;

Set up unit tests ==> 是否安装 单元测试工具 目前我们不需要 所以 n 回车;

Setup e2e tests with Nightwatch ==> 是否需要 端到端测试工具 目前我们不需要 所以 n 回车;
使用到的下载工具,我这里以 npm 为例
等待安装 vue 项目即创建了 vue 框架项目:

image

2.测试 vue 框架项目是否搭建成功

打开 cmd 控制台

  1. 打开项目所在位置的文件夹
  2. 运行 cnpm start

image

image

点击访问网址: http://localhost:8081,显示

image

表示项目构建成功!

5.使用 element-ui 框架

1.安装 element 框架依赖

在 cmd 控制台输入

1
cnpm i element-ui -S

image

安装完毕

2.在 main.js 中引入 element-ui

main.js 在(你的项目)\src 文件夹下,我这里是 element-test\src\

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui';
//引入elementui
import 'element-ui/lib/theme-chalk/index.css';
Vue.config.productionTip = false

//在vue中使用elementui
Vue.use(ElementUI);
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})

如上图,引入并使用 element-ui

3.element-ui 的使用实例

1.在 src\components 的目录下新建一个组件(这里以 Button.vue 为例)

image

2.注册 Button.vue 组件

在 src\router\index.js 中写入 import Button from “../components/Button”; 路由 组件 如下图:

image

3.修改 App.vue 文件

image

4.引入 element-ui 样式(进入element-ui 官网可使用其他大量组件)

修改 Button.vue 文件,写入以下代码:

1
2
3
4
5
6
7
8
<el-row>
<el-button plain>朴素按钮</el-button>
<el-button type="primary" plain>主要按钮</el-button>
<el-button type="success" plain>成功按钮</el-button>
<el-button type="info" plain>信息按钮</el-button>
<el-button type="warning" plain>警告按钮</el-button>
<el-button type="danger" plain>危险按钮</el-button>
</el-row>

image

保存在运行此项目(在控制台使用 cnpm start)

点击超链接

image

即成功引用 element-ui 框架

6.总结

1.安装 nodejs

2.在 cmd 中:

1.换源 :npm install -g cnpm –registry=https://registry.npm.taobao.org

2.安装 vue:

1
cnpm install --global vue-cli

3.新建 vue 框架项目(切换至 WS 控制台)

1
vue init webpack element-test

4.下载 element-ui 依赖

1
cnpm i element-ui -S

5.修改 main.js 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui';
//引入elementui
import 'element-ui/lib/theme-chalk/index.css';
Vue.config.productionTip = false

//在vue中使用elementui
Vue.use(ElementUI);
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})

重点看//后面的注释

axios 是基于 promise 封装的异步请求插件,其中包含两套核心,基于浏览器的 XHR 核心,基于服务端 http 模块,可以兼容浏览器与服务端两个业务场景,同时通过了多种传参方式,拦截全局请求,全局数据格式化等功能,方便开发者使用。

一、发送请求

1. 传统用法 类$.Ajax

1
2
3
4
5
6
7
8
9
// 发送 POST 请求
axios({
method: '',//类型
url: '',// url
data: { // data
}
})
.then(res=>{})
.catch(err=>{})

2. get 方法抽离

1
2
3
4
5
6
// axios.post(url,{params:''})
axios.get('/user', {
params: {
ID: 12345
}
})

3. post 方法抽离

1
2
3
4
// axios.post(url,body)
axios.post('/user', {
ID: 12345
})

一定要注意两者参数传递时的区别,否则容易在项目中踩坑

二、创建请求实例

通过创建实例,可以避免在使用时 重复填写相同配置

1. 在 vue 项目中创建一个实例,并挂载到全局

1
2
3
4
5
6
7
8
9
10
Vue.prototype.$http = axios.create({
baseURL: 'http://www.',//配置一个默认域名
timeout: 5000, // 超时时间
headers:{'Content-Type':'application/json;charset=utf8'} // 配置header
});

// 使用
this.$http()
this.$http.get()
this.$http.post()

2. 其它配置项可参考官方文档

三、多接口并发统一处理

由于 axios 基于 promise 开发,所以 promise.all(),Promise.race()同样适用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var p1 = new Promise((resolve, reject) => {
this.$axios.get(url).then(res=>{
resolve(res)
}).catch(err=>{
reject(err)
})
});

var p2 = new Promise((resolve,reject)=>{
this.$axios.get(url).then(res=>{
resolve(res)
}).catch(err=>{
reject(err)
})
})

// 请求都完成后执行
// 调用Promise.all().then(res=>{})
Promise.all([p1,p2]).then(res=>{
console.log(res);
})
}

// 有一个请求完成即执行
// 调用Promise.race().then(res=>{})
Promise.race([p1,p2]).then(res=>{
console.log(res);
})
}

四、全局拦截器

请求,响应被 then 或 catch 处理前拦截它们,比如添加其它全局请求数据(token,签名),集中处理 catch 报错,判断请求是否成功,避免分开处理。

1. 向服务器发出请求前拦截处理

1
2
3
4
5
6
7
8
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});

2. 被服务器响应后拦截处理

1
2
3
4
5
6
7
8
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});