进阶
1. Nodejs
1.1. 准备
安装Nodejs
brew install node
1.2. 介绍
Node
- Node是一个让JavaScript运行在服务端的平台。是一门脚本语言。
- 发布于2009年5月,由Ryan Dahl开发。
- 实质是对Chrome V8引擎进行了封装。V8引擎执行JavaScript的速度快,性能高
Nodejs
- 实质就是运行在服务端的JavaScript。底层架构是JavaScript。
- 是一个基于Chrome Javascript运行时建立的一个平台。
- 文件名的后缀是.js
- 是一个事件驱动I/O服务端JavaScript环境。
- 运行的命令为node 文件名
1.3. 入门案例
hello.js
console.log("hello");
运行
node hello.js
结果
hello
1.4. 实现请求和响应
httpserver.js
// require导入模块 类似于import const http = require('http'); // 创建一个httpserver服务 http.createServer(function (request, response) { response.writeHead(200, { 'Content-type': 'text/html' }); response.end("<strong>hello, server.</strong>"); }).listen(8888); console.log("启动成功,地址为http://localhost:8888")
启动
node httpserver.js
访问
1.5. 操作MySQL数据库
安装mysql依赖
npm install mysql
db.js
// 导入mysql依赖 const mysql = require('mysql'); // 创建一个mysql的connection对象 // 配置数据库信息 var connection = mysql.createConnection({ host: "127.0.0.1", port: 3306, user: "root", password: "root", database: "mybatis" }); // 打开连接 connection.connect(); // 执行查询操作 connection.query("select * from user", function (error, results, fields) { if (error) throw error; console.log(results); }); // 关闭连接 connection.end();
启动
node db.js
问题:
MySQL8不支持,提示如下
Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
解决方法见这里。
2. ES6
2.1. 介绍
ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,European Computer Manufacturers Association)通过ECMA-262标准化的脚本程序设计语言。这种语言在万维网上应用广泛,它往往被称为JavaScript或JScript,所以它可以理解为是JavaScript的一个标准,但实际上后两者是ECMA-262标准的实现和扩展。
ECMAScript定义了:
[语言语法] – 语法解析规则、关键字、语句、声明、运算符等。
[类型]– 布尔型、数字、字符串、对象等。
[原型和继承]
内建对象和函数的
[标准库] – [JSON]、[Math]、[数组方法]、[对象自省方法]等。
ECMAScript是前端js的语法规范,可以应用在各种js环境中。如:浏览器或者node.js环境。
2.2. 语法
let和const
let是可变变量,可以解决var的变量穿透问题。
const是常量,不可以再次赋值。
- 小程序、uniapp或者脚手架,可以用let和const
- web开发,还是用var,因为一些低版本的浏览器还是不支持let和const
模版字符串
// 传统
let a = "a";
let b = "b";
// 传统写法
let str1 = a + "---" + b;
// 使用模版字符串后
let str2 = `${a}---${b}`;
// 换行
let str3 = `
hello world.
`;
用途:
- 基本字符串格式化,将表达式在字符串中进行拼接,${}指定要拼接的变量名。
- 支持换行。
默认参数
形式参数可以传递默认参数
function add(a=100, b=100) {
return a+b;
}
console.log(add(a));
如果传递了对应的参数,则默认参数不会生效;如果没有传递对应的参数,则会用默认值进行填充。
箭头函数
此处可以参见这里。
条件都差不多,Java是->
,js是=>
var a = (a,b) => a+b;
var c = c=>c;
对象初始化的简写
简写前提:
- 对象以key : value存在。
- key和变量名一致,可以只定义一次。
- 如果value是一个函数,可以把
: function
去掉,只留下()
即可。
let user = {
username : 'zhangsan',
password : '123456',
go:function() {
console.log(`username: ${username}, password: ${password}`);
}
}
// 使用es6可以简写成
let username = 'zhangsan';
let password = '123456';
let user1 = {
username,
password,
go(){
console.log(`username: ${username}, password: ${password}`);
}
}
使用场景
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="">
<p>账号:<input type="text" id="account"></p>
<p>密码<input type="password" id="password"></p>
<p><input type="button" value="登陆" id="loginbtn"></p>
</form>
<script>
$("#loginbtn").on("click", function() {
var account = $("#account").val();
var password = $("#password").val();
var param = {account, password};
$.ajax({
type:"post",
url:"xxx",
data:param,
success(){
}
})
});
</script>
</body>
</html>
对象解构
let user = {
username : 'zhangsan',
password : '123456',
go:function() {
console.log(`username: ${username}, password: ${password}`);
}
}
// 获取对象的三种不同的方式
// 第一种.
var username1 = user.username;
var password1 = user.password;
var go1 = user.go;
// 第二种[]
var username2 = user["username"];
var password2 = user["password"];
var go2 = user["go"];
// 第三种{
var {username, password, go} = user;
console.log(username);
console.log(password);
console.log(go);
// 第三种名字和对象参数名需要保持一致
传播操作符[...]
解构后剩余还没有赋值的参数,可以用传播操作符赋给一个新的对象。
var {username, password, ... user2} = user;
console.log(username);
console.log(password);
console.log(user2);
数组中的map方法
可以将原数组中的所有元素通过一个函数进行处理,将数组中对象的值进行curd操作,并回填到原来位置中。
let arr = [1,2,3,4,5,6,7];
let newarr = [];
// 传统
for (let i = 0; i < arr.length; i++) {
newarr.push(arr[i] * 2);
}
console.log(newarr);
// es6
let newarr2 = arr.map(ele => ele * 2);
console.log(newarr2);
数组中的reduce方法
reduce(function(),初始值(可选)) :
接收一个函数(必须)和一个初始值(可选),该函数接收两个参数:
- 第一个参数是上一次reduce处理的结果
- 第二个参数是数组中要处理的下一个元素 reduce() 会从左到右依次把数组中的元素用reduce处理,并把处理的结果作为下次reduce的第一个参数。如果是 第一次,会把前两个元素作为计算参数,或者把用户指定的初始值作为起始参数
let arr = [1,2,3,4,5,6,7];
let res = arr.reduce((a,b) => a+b);
console.log(res);
其中,map和reduce方法有点类似于流式计算。
3. NPM包管理器
NPM全称Node Package Manager,是Node.js包管理工具,是全球最大的模块生态系统,里面所有的模块都是开源免费的;也是Node.js的包管理工具,相当于前端的Maven 。
3.1. 安装npm
npm install moduleName
:安装模块到项目目录下npm install -g moduleName
:-g的意思是将模块安装到全局,具体安装到磁盘哪个位置要看npm config prefix的位置npm install -save moduleName
:–save的意思是将模块安装到项目目录下, 并在package文件的dependencies节点写入依赖,-S为该命令的缩写npm install -save-dev moduleName
:–save-dev的意思是将模块安装到项目目录下,并在package文件的devDependencies节点写入依赖,-D为该命令的缩写
一般安装nodejs后会自动安装npm。
# 安装npm
brew install node
# 查看是否已经安装和版本信息
npm -v
使用
在文件夹内使用npm init
初始化npm项目。
# 建立一个空文件夹,在命令提示符进入该文件夹 执行命令初始化
npm init
# name: 项目名称
# version: 项目版本号
# description: 项目描述
# keywords: {Array}关键词
# script: 自定义脚本
# 最后会生成package.json文件,这个是包的配置文件,相当于maven的pom.xml
# 如果想直接生成 package.json 文件,那么可以使用命令
npm init -y
生成文件如下
{
"name": "npm",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
3.2. 自定义脚本
其中,scripts可以自定义脚本,如上面代码中的test,当执行npm run test
的时候就会执行echo \"Error: no test specified\" && exit 1
。
3.3. 换源
# 更换源为淘宝镜像
npm config set registry https://registry.npm.taobao.org
# 查看npm配置信息
npm config list
3.4. 安装模块
npm install mysql
# 指定版本号
npm install [email protected]
# devDependencied节点:开发时依赖包,项目打包到生产环境的时候不包含该依赖。
# 使用-D参数将依赖添加到devDependencied节点
npm install -D mysql
# 或者可以使用 npm install --save-dev mysql
# 全局安装
# 查看默认安装路径
npm config get prefix
# macOS中默认安装路径为 /usr/local/lib/node_modules文件夹中
npm config set prefix path
# 将全局包安装在指定路径下
# 使用全局方式安装依赖,会安装到上面全局安装的路径
npm install -g mysql
# 根据package.json配置的依赖初始化项目,自动添加依赖
npm install
安装模块后在会package.json中自动添加依赖坐标,如下:
npm install mysql
"dependencies": {
"mysql": "^2.18.1"
}
方便复用npm install
.
3.5. 更新和卸载
# 更新包
npm update mysql
# 全局更新
npm update -g mysql
# 卸载包
npm uninstall mysql
# 全局卸载
npm uninstall -g mysql
3.6. 使用依赖
const mysql = require('mysql');
3.7. CNPM
cnpm是中国npm镜像的客户端
npm install cnpm -g --registry=https://registry.npm.taobao.org
cnpm -v
# cnpm用法和npm相同
同步包:
cnpm sync [moduleName]
查看包文件:
cnpm doc [name]
cnpm doc -g [name] # open git web url directly
构建私有 npm:
npm install cnpm -g
# then alias it
alias mynpm='cnpm --registry=http://registry.npm.example.com \
--registryweb=http://npm.example.com \
--userconfig=$HOME/.mynpmrc'
全局安装权限不足的问题:
sudo chown -R (whoami)(npm config get prefix)/{lib/node_modules,bin,share}
4. Babel
Babel是一个转码器,可以将ES6代码转换为ES5代码,从而在不支持ES6某些高级语法的浏览器或者Node.js环境中运行。
使用Babel后可以不同担心现有环境是否支持的问题。
4.1. 安装
npm install -g babel-cli
babel --version
4.2. 使用
这里使用上面的新特性进行实验,但是有些并不能转换。
src/example.js
``js let a = "a"; let b = "b"; let str2 =
${a}---${b}`;let str3 =
hello world.
;function add(a=100, b=100) {
return a+b;
}
console.log(add(a));
let username = 'zhangsan'; let password = '123456'; let user1 = { username, password, go() {
console.log(`username: ${username}, password: ${password}`);
} };
let user = {
username: 'zhangsan',
password: '123456',
go: function () {
console.log(username: ${username}, password: ${password}
);
}
};
let arr = [1, 2, 3, 4, 5, 6, 7]; let newarr = []; let newarr2 = arr.map(ele => ele * 2); console.log(newarr2);
2. 项目路径下配置.babelrc
```json
{
"presets": ["es2015"],
"plugins": []
}
项目中安装转码器
npm install --save-dev babel-preset-es2015
进行转码
# 指定文件转码 babel src/example.js -o dist/example.js # 整个目录转码 babel src -d dist
转码后
"use strict"; var a = "a"; var b = "b"; var str2 = a + "---" + b; var str3 = "\nhello world.\n"; function add() { var a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 100; var b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100; return a + b; } console.log(add(a)); var username = 'zhangsan'; var password = '123456'; var user1 = { username: username, password: password, go: function go() { console.log("username: " + username + ", password: " + password); } }; var user = { username: 'zhangsan', password: '123456', go: function go() { console.log("username: " + username + ", password: " + password); } }; var arr = [1, 2, 3, 4, 5, 6, 7]; var newarr = []; var newarr2 = arr.map(function (ele) { return ele * 2; }); console.log(newarr2);
Babel可以自定义脚本
"build": "babel src -d dist"
5. 模块化
js没有类、包、等概念,不是一种模块化的编程语言。使用复杂,而且需要引用的话原先需要拷贝所有源代码。使用模块化开发之后,可以方便复用代码,简化开发。
模块化开发规范有两种:
Common JS模块化规范
ES6模块化规范
5.1. Common JS规范
每个文件就是一个模块,有自己的作用域。在一个文件里面定义的常量、函数、类都是私有的,对其他文件不可见。
创建一个工具模块
function add(a, b) { return a + b; } function sub(a, b){ return a - b; } function mult(a, b) { return a * b; } function div(a, b) { return a / b; } // 导出模块,需要导出指定的方法外部才能导入进行使用 module.exports = { add: add, // 两个名字相同,可以省略 sub, mult }
调用
// 路径前面必须有 ./ const util = require("./util") console.log(util.add(1, 2)); console.log(util.sub(1, 2)); console.log(util.mult(1, 2)); // 报错 // console.log(util.div(1, 2));
5.2. ES6规范
具体有两种方式
方式一
src/userApi.js
export function getList() { console.log("获取列表"); } export function save() { console.log("保存数据"); }
src/userComponent.js
import {getList, save} from './userApi.js' getList(); save();
node不能直接运行,需要Babel进行转换
转换后的结果
src/userApi.js
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getList = getList; exports.save = save; function getList() { console.log("获取列表"); } function save() { console.log("保存数据"); }
src/userComponent.js
'use strict'; var _userApi = require('./userApi.js'); (0, _userApi.getList)(); (0, _userApi.save)();
成功运行。
方式二
实际上开发的时候,更常见的写法如下:
src/userApi.js
export default { getList() { console.log("获取列表"); }, save() { console.log("保存数据"); } }
src/userComponent.js
import user from './userApi.js' user.getList(); user.save();
node不能直接运行,需要Babel进行转换
转换后的结果
src/userApi.js
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = { getList: function getList() { console.log("获取列表"); }, save: function save() { console.log("保存数据"); } };
src/userComponent.js
'use strict'; var _userApi = require('./userApi.js'); var _userApi2 = _interopRequireDefault(_userApi); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } _userApi2.default.getList(); _userApi2.default.save();
成功运行。
6. Webpack
6.1. 概述
是一个前端资源加载/打包工具。可以对模块的依赖关系静态分析,然后按照制定规则生成对应的静态资源。Webpack可以将多种静态资源js, css, less等转换成一个静态文件,减少了页面的请求。
本质上, webpack是一个现代JavaScript应用程序的静态模块打包器(module bundler) 。当webpack处理应用程序时, 它会递归地构建一个依赖关系图(dependency graph) , 其中包含应用程序需要的每个模块, 然后将所有这些模块打包成一个或多个bundle.
Webpack是当下最热门的前端资源模块化管理和打包工具, 它可以将许多松散耦合的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分离,等到实际需要时再异步加载。
6.2. 安装
npm install -g webpack webpack-cli
webpack -v
# 合成css文件需要安装
npm install --save-dev style-loader css-loader
6.3. 打包
src/common.js
exports.add = function (a, b) { return a + b; } exports.minus = function (a, b) { return a - b; }
src/utils.js
exports.info = function (str) { return str; }
src/style.css
body{ color:red; background-color: aqua; }
src/main.js
const common = require("./common"); const utils = require("./utils"); require("./style.css"); document.write(utils.info("1+2=") + common.add(1, 2)); console.log(utils.info("1-2=" + common.minus(1, 2)));
在项目根目录下创建配置文件webpack.config.js
- entry:入口文件, 指定Web Pack用哪个文件作为项目的入口
- output:输出, 指定WebPack把处理完成的文件放置到指定路径
- module:模块, 用于处理各种类型的文件
- plugins:插件, 如:热更新、代码重用等
- resolve:设置路径指向
- watch:监听, 用于设置文件改动后直接打包
const path = require("path"); //Node.js内置模块 module.exports = { entry: './src/main.js', //配置入口文件 output: { path: path.resolve(__dirname, './dist'), //输出路径,__dirname:当前文件所在路径 filename: 'bundle.js' //输出文件 }, module: { rules: [ { test: /\.css$/, //打包规则应用到以css结尾的文件上 use: ['style-loader', 'css-loader'] } ] } }
编译
这里也可以做成自定义脚本
webpack --mode=development # 实时编译,检测到文件修改,自动更新js文件 webpack -w # 或者 webpack -watch
编译后的文件加密过,比较安全。
测试