一、行为层(JavaScript)
JavaScript 一门弱类型脚本语言,其源代码在发往客户端运行之前不需经过编译,而是将文本格式的字符代码发送给浏览器由浏览器解释运行。
Native 原生 JS 开发
原生 JS 开发,也就是让我们按照 【ECMAScript】 标准的开发方式,简称是 ES,特点是所有浏览器都支持。截止到(2018 年 12 月 04 日),ES 标准已发布如下版本:
ES3
ES4(内部,未正式发布)
ES5(全浏览器支持)
ES6(常用,当前主流版本)
ES7
ES8
ES9(草案阶段)
区别就是逐步增加新特性。
TypeScript 微软的标准
TypeScript 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。由安德斯·海尔斯伯格(C#、Delphi、TypeScript 之父;.NET 创立者)主导。
该语言的特点就是除了具备 ES 的特性之外还纳入了许多不在标准范围内的新特性,所以会导致很多浏览器不能直接支持 TypeScript 语法,需要编译后(编译成 JS)才能被浏览器正确执行。
JavaScript 框架
- jQuery:大家熟知的 JavaScript 框架,优点是简化了 DOM 操作,缺点是 DOM 操作太频繁,影响前端性能;在前端眼里使用它仅仅是为了兼容 IE6、7、8;
- Angular:Google 收购的前端框架,由一群 Java 程序员开发,其特点是将后台的 MVC 模式搬到了前端并增加了模块化开发的理念,与微软合作,采用 TypeScript 语法开发;对后台程序员友好,对前端程序员不太友好;最大的缺点是版本迭代不合理(如:1代 -> 2代,除了名字,基本就是两个东西;截止发表博客时已推出了 Angular6)
- React:Facebook 出品,一款高性能的 JS 前端框架;特点是提出了新概念 【虚拟 DOM】 用于减少真实 DOM 操作,在内存中模拟 DOM 操作,有效的提升了前端渲染效率;缺点是使用复杂,因为需要额外学习一门 【JSX】 语言;
- Vue:一款渐进式 JavaScript 框架,所谓渐进式就是逐步实现新特性的意思,如实现模块化开发、路由、状态管理等新特性。其特点是综合了 Angular(模块化) 和 React(虚拟 DOM) 的优点;
- Axios:前端通信框架;因为 Vue 的边界很明确,就是为了处理 DOM,所以并不具备通信能力,此时就需要额外使用一个通信框架与服务器交互;当然也可以直接选择使用 jQuery 提供的 AJAX 通信功能;
UI 框架
- Ant-Design:阿里巴巴出品,基于 React 的 UI 框架
- ElementUI:饿了么出品,基于 Vue 的 UI 框架
- Bootstrap:Twitter 推出的一个用于前端开发的开源工具包
- AmazeUI:又叫“妹子 UI”,一款 HTML5 跨屏前端框架
- JavaScript 构建工具
- Babel:JS 编译工具,主要用于浏览器不支持的 ES 新特性,比如用于编译 TypeScript
- WebPack:模块打包器,主要作用是打包、压缩、合并及按序加载
注:以上知识点已将 WebApp 开发所需技能全部梳理完毕
三端统一
混合开发(Hybrid App)
主要目的是实现一套代码三端统一(PC、Android、iOS)并能够调用到设备底层硬件(如:传感器、GPS、摄像头等),打包方式主要有以下两种:
- 云打包:HBuild -> HBuildX,DCloud 出品;API Cloud
- 本地打包: Cordova(前身是 PhoneGap)
微信小程序
详见微信官网,这里就是介绍一个方便微信小程序 UI 开发的框架:WeUI
后端技术
前端人员为了方便开发也需要掌握一定的后端技术,但我们 Java 后台人员知道后台知识体系极其庞大复杂,所以为了方便前端人员开发后台应用,就出现了 NodeJS 这样的技术。
NodeJS 的作者已经声称放弃 NodeJS(说是架构做的不好再加上笨重的 node_modules,可能让作者不爽了吧),开始开发全新架构的 Deno
既然是后台技术,那肯定也需要框架和项目管理工具,NodeJS 框架及项目管理工具如下:
Express:NodeJS 框架
Koa:Express 简化版
NPM:项目综合管理工具,类似于 Maven
YARN:NPM 的替代方案,类似于 Maven 和 Gradle 的关系
二、入门
js引入、开发工具使用
- 引入外部js文件
<script type="text/javascript" src="js/test.js">
</script>
- 定义变量
//定义变量
var score = 90;
- 条件控制
//条件控制
if (score < 60) {
console.log("不及格了");
}else if(score<80){
console.log("及格了");
}else {
console.log("优秀");
}
- 浏览器开发者工具
在浏览器的控制台打印xxx
console.log(xxx)
数据类型基本介绍
- Number
12 //整数
23.3 //浮点
1.22e3 //科学计数法=1220
-22 //负数
NaN //not a Number
Infinity //表示无限大
- 字符串
'aaa'
"aaa"
- 布尔值
true、false
- 逻辑运算
与 或 非
&& || !
- 比较运算法
= 赋值
== 等于(类型不一样,值一样也会相等),最好使用===
=== 绝对等于(类型一样,值一样才为true)
双等号与单等号的区别。参考:http://c.biancheng.net/view/5461.html">http://c.biancheng.net/view/5461.html
NaN===NaN 为false,因为它自己也不等于自己。
可以通过isNaN(var1)来判断一个东西是不是NaN
- 浮点数,精度丢失
精度缺失计算相等
- null和undefined
null为空,undefined为未定义。
- 数组
使用括号
如果数据越界为undefined
var arr = [1,2,'hehe',null,true,undefined];
let array = new Array(1,2,'three');
console.log(arr);
- 定义对象和取对象
- 使用大括号,每个属性之间用逗号隔开。
//定义对象
var person = {
name:"wei",
age:3,
skill:['js','java','web']
}
- 严格检查模式
预防js的随意性导致产生的一些问题。它必须写在js的第一行。
局部变量推荐使用let
'use strict';
i= 1;//将会出现错误。而没有严格检查都不会报错。
数据类型
字符串
单双引都一样。
转义字符 \
\'
\n
\t
\uXXXX unicode字符
\x41 = A ,ASCLL字符
- 模板字符串
let name = '秦始皇';
let msg = `我是${name}`;
字符串方法
- 字符串的长度
str.length
- 字符串不可变。
赋值也不会改变
- 大小写转换方法
stu.toUpperCase();
stu.toLowerCase();
- indexOf
stu1.indexOf('s');//返回对应的索引
- substring 和 substr 函数
var str = '0123456';
str.substring(4); //单个参数,表示取这个索引至结尾
str.substring(1,4);//两个参数,表示取这2个数之间。半开半闭区间。
str.substr(4); //单参数与substr一样
str.substr(1,4);//双参数表示,从1索引开始取,取4个。
数组(js数组为可变)
- arr.length 可以改变数组的长度。
- 超过部分为未定义。小于数组长度则数据丢失。
- arr.indexOf 通过元素获取下标索引
- slice 与substring一样
- push,pop 操作尾部
push:压入尾部
pop:弹出尾部的一个元素
- unshift(),shift() 操作头部
- 头部添加和删除。
- sort() 排序
- 元素反转 reverse
- concat 数组拼接,返回新数组,不改变原数组
- 连接符join
打印拼接数组,使用特定的字符串连接 - 多维数组
对象
任意个键值对。
var 对象名 = {
属性名1:属性值,
属性名2:属性值,
属性名3:属性值
}
var person = {
name:'wei',
age:18,
address:'福建'
}
- 获取对象
- 对象赋值
- 使用不存在的属性不会报错,结果为未定义
- 动态的添加和删减属性
person.higher = 170;
delete person.higher;
- 判断属性值是否在这个对象中。属性 in 对象
必须要写引号。
- 判断一个属性是否是这个对象自身拥有的 hasOwnProperty
流程控制
- if 与java一致。
- while与java一致。
- for循环与java一致。
for (let i = 0; i < 10; i++) {
}
- 增强for
var arr = [1,2,3];
arr.forEach(function (item) {
alert(item);
})
- for … in
var arr = [1,66,7];
for (var numer in arr){
alert(arr[numer]);
}
- for … of
var arr = [1,66,7];
for(let num of arr){
console.log(num)
}
Map和Set
- 定义Map
var map = new Map([['tom',100],['nick',90],['jack',80]]);
var name = map.get('tom');//获取
map.set('user',20);//添加
map.delete('user');//删除
- 取元素
- 添加元素
- 定义Set
- 添加、删除元素
- 是否包含
- map遍历
var map = new Map([['tom',100],['nick',90],['jack',80]]);
//forEach
map.forEach(function (key,value) {
console.log(value,key)
})
// for of
for (let mapElement of map) {
console.log(mapElement[0]);console.log(mapElement[1]);
}
- set 遍历
var set = new Set([1,3,4,5,7]);
//forEach
set.forEach(function (value) {
console.log(value);
});
// for of
for(var value of set){
console.log(value);
}
函数及面向对象
定义函数
- 定义函数的两种方式
- 第一种方式
function abs(x){
if (x>0){
return x;
}else {
return -x;
}
}
let abs1 = abs(9);
- 第二种方式、匿名函数
var fun = function (x) {
console.log("function...fun");
}
- 调用函数
如果参数少了,则结果为NAN,如果参数多了,则对结果没有影响。
- 参数数组 arguments
传递进来的参数是一个数组。
- ES6新特性 rest
function add(x, y, ...rest) {
console.log(x + y);
console.log(rest);//x,y之后的参数
return x + y;
}
变量的作用域
- var 定义变量实际是有作用范围的。
- 不同函数可以使用相同的变量名。
- 内部函数可以访问外部函数的成员,反之不行。
function fun1() {
var x = 1;
function fun2(){
var y = x+1;
}
var z = y - 2; // Uncaught ReferenceError: y is not defined
}
- js变量定义规范,都放在头部。
function fun1() {
// var x,y,z....;
...
}
- 全局函数、全局变量
var x = 1;
function fun1() {
console.log(x);
}
- 全局变量window
- 默认所有的全局变量,都会自动绑定在window
var x = '1';
window.alert(x);
var old_alert = window.alert;
window.alert = function () {
};
window.alert(2);
window.alert = old_alert;
window.alert(3);
- js实际上只有一个全局作用域,任何变量(函数可以视为变量),假设没有再函数作用范围内找到,就会向外查找,如果全局作用域都没有找到,报错RefrenceError.
- 规范
由于我们所有的全局变量都会绑定到我们window上。如果使用不同的js文件,使用了相同的全局变量,就会产生冲突。
var weiApp = {};
weiApp.age = 18;
weiApp.add = function (a, b) {
return a + b;
}
- 把自己的代码全部都放入自己定义的唯一空间名字中,降低全局命名冲突的问题。
jQuer就是这么做的。$ = jquery - 局部作用域 let
让 i 在for内生效。使用let去定义局部作用域的变量。
for (let i = 0; i < 100; i++) {
console.log(i);
}
- 常量 const
ES6 之前,常量为约定俗成。现在为语法支持。
const PI = 3.141592653;
PI=4;
方法
- js对象里的方法。
var person = {
name:'wei',
birthDay:1999,
age:function () {
return new Date().getFullYear()-this.birthDay;//person.birthDay
}
}
优化方法:
调用方法和结果与上面一致。
var person = {
name:'wei',
birthDay:1999,
age:getAge
}
function getAge(){
return new Date().getFullYear()-this.birthDay;//person.birthDay
}
this 默认指向调用它的那个对象。
- apply
在js中,可以控制this指向。
var person = {
name:'wei',
birthDay:2000,
age:getAge
}
var person2 = {
name:'wei2',
birthDay:1999,
age:getAge
}
function getAge(){
return new Date().getFullYear()-this.birthDay;//person.birthDay
}
getAge.apply(person,[]);//调用语句。this指向了person,参数为空。
内部对象
- 基本对象
typeof 1
"number"
typeof '1'
"string"
typeof []
"object"
typeof {}
"object"
typeof person
"object"
typeof NaN
"number"
typeof true
"boolean"
typeof Math.asin
"function"
typeof undefined
"undefined"
- Date
- 基本使用
var now = new Date(); //Fri Aug 07 2020 23:38:09 GMT+0800 (中国标准时间)
now.getFullYear(); //年
now.getMonth(); //月
now.getDate(); //日
now.getDay(); //星期 0-6
now.getHours(); //时
now.getMinutes(); //分
now.getSeconds(); //秒
now.getTime(); //时间戳 1596814678163
now.toLocaleDateString(); //"2020/8/7"
now.toLocaleTimeString(); //"下午11:38:09"
now.toLocaleString(); //"2020/8/7 下午11:38:09"
- JSON
var jsObj = {
name:'zhangSan',
age:'18'
};
var jsonStr = '{"name":"zhangSan","age","18"}';
// JSON字符串转换为JS对象
var JsObject = JSON.parse(jsonStr);
// JS对象转换为JSON字符串
var jsonString = JSON.stringify(jsObj);
//浏览器控制台查看输出
console.log(jsonObject);
面向对象编程
- 原型对象
js,java,c#,c++ 。js有些区别。
- 类:模板
- 对象:具体的实例
原型:
<script>
var user = {
name:"wei",
age:3,
run:function () {
console.log(this.name+" run ...");
}
};
var zhangsan = {
name:"zhangsan"
};
//小明的原型 是 user
zhangsan.__proto__ = user;
</script>
user
{name: "wei", age: 3, run: ƒ}
zhangsan
{name: "zhangsan"}
user.run();
wei run ...
zhangsan.run();
zhangsan run ...
- class继承
ES6
ES6之后
// 定义一个学生类
class Student{
constructor(name) {
this.name = name;
}
hello(){
console.log('hello...'+this.name);
}
}
var zhangsan = new Student("zhangsan");
var lisi = new Student("lisi");
lisi.hello();
hello...lisi
zhangsan.hello();
hello...zhangsan
class Student{
constructor(name) {
this.name = name;
}
hello(){
console.log('hello...'+this.name);
}
}
class Pupil extends Student{
constructor(name,grade) {
super(name);
this.grade = grade;
}
myGrade(){
console.log('我是小学生');
}
}
var zhangsan = new Student("zhangsan");
var lisi = new Pupil("lisi",1);//本质还是Student
- 原型链
__ proto __
操作BOM对象(重点)
- 浏览器对象模型
- window 重要
代表浏览器窗口
window.innerWidth
813
window.innerHeight
803
window.outerHeight
824
window.outerWidth
1536
- navigator 不建议使用
navigator ,封装了浏览器的信息。
大多数时候,我们不会使用它,因为它会被人为修改。
不建议使用这些属性来判断和编写代码。
navigator.appName
"Netscape"
navigator.appVersion
"5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36"
navigator.userAgent
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36"
navigator.platform
"Win32"
- screen
代表屏幕的尺寸,在我2个不同的显示器上,结果是不一样的。
screen.width
1536
screen.height
864
screen.height
1080
screen.width
1920
- location 重要
代表当前页面的url信息。
host: "www.baidu.com"
href: "https://www.baidu.com/"
protocol: "https:"
reload: ƒ reload()
//设置新的地址
location.assign("https://www.sina.com.cn/");
- document
document代表当前的页面,HTML DOM
- 获取具体的文档树节点
//获取具体的文档树节点
var d = document.getElementById('app');
//获取cookie
document.cookie
"BIDUPSID=12BF1A485829DD57E527B5DB6FFE71E7;
- 劫持cookie原理
获取你额cookie上传到它的服务器。 - 服务端可以设置cookie:httpOnly
- history 不建议使用
//后退,前进。
history.back();
history.forward();
操作Dom
文档对象模型 document object model
- 核心
- 更新:更新dom节点
- 遍历dow节点:得到dom节点
- 删除:删除一个dom节点
- 添加:添加一个新的节点
要操作一个dom节点,就必须要先获得这个dom节点。
- 更新
操作文本
<body>
<div id="div1">
</div>
</body>
<script>
var div1 = document.getElementById('div1');
//修改文本的值(不能解析标签)
div1.innerHTML = '<h1>123</h1>'
//解析html文本标签
div1.innerText = 111
//操作css
div1.style.color = 'red'; //颜色设置
div1.style.fontSize = '20px'; // 横杆变为驼峰
div1.style.padding = '2em'; //内边距
</script>
- 删除节点
<div id="div1">
<p id="p1">p1</p>
<p id="p2">p2</p>
<p id="p3">p3</p>
</div>
<script>
var div1 = document.getElementById('div1');
var p1 = document.getElementById('p1');
var p2 = document.getElementById('p2');
var p3 = document.getElementById('p3');
p2.remove();
undefined
p3.parentElement.removeChild(p3);
<p id="p3">p3</p>
</script>
- 插入节点
- 插入已有的节点(移动)
<body>
<p id="p4">p4</p>
<div id="div1">
<p id="p1">p1</p>
<p id="p2">p2</p>
<p id="p3">p3</p>
</div>
</body>
<script>
var div1 = document.getElementById('div1');
var p1 = document.getElementById('p1');
var p2 = document.getElementById('p2');
var p3 = document.getElementById('p3');
var p4 = document.getElementById('p4');
div1.appendChild(p4);
</script>
- 插入新创建的节点。
let new_p = document.createElement("p");
new_p.setAttribute("id","new_p");
new_p.innerText="新创建了一个p节点";
div1.appendChild(new_p);
操作表单
<body>
<form action="http://www.baidu.com/" method="post" onsubmit="return m()">
用户名:<input type="text" id="username" name="username" /> <br/>
密码:<input type="password" id="password" />
<input type="hidden" id="md5-password" name="password" >
<button type="submit">提交</button>
</form>
</body>
<script>
function m() {
var password = document.getElementById("password");
var md5Pwd = document.getElementById("md5-password");
md5Pwd.value = md5(password.value);
//可以校验判断表单内容,true就是通过提交。false就是阻止提交。
return true;
}
</script>
表单提交取决于name属 性。
jQuery
- 选择器
<body>
<a id="a" class="a-name" href="">点我</a>
<a id="a2" class="a-name2" href="">点我2</a>
</body>
<script>
$(".a-name").click();//class选择器
$("#a").click();//id选择器
$("a").click();//标签选择器
</script>
- 事件
<body>
<div id="divMove" class="divMove" style="width: 500px;height: 500px ;background-color: aquamarine" ></div>
</body>
<script>
$(function () {
$("#divMove").click(function () {
console.log("点击了");
});
});
- 操作dom
<body>
<ul id="lang">
<li id="java" >java</li>
<li id="python" name="python" >python</li>
<li id="c">c</li>
</ul>
</body>
<script>
$(function () {
$("#lang #java").html();//获取
$("#lang #java").html("java++");//设置
$("#lang").html();//获取
$("#lang").html('<li id="c++">c++</li>');//设置
});
</script>
显示和隐藏元素。
JS 定时器
- setInterval() :按照指定的周期(以毫秒计)来调用函数或计算表达式。方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。
- setTimeout() :在指定的毫秒数后调用函数或计算表达式。
<script>
//每秒执行一次。
var interval = window.setInterval(f,1000);
//2秒后执行一次。
var timeout = window.setTimeout(f,2000);
//清除定时器
clearInterval(interval);
clearInterval(timeout);
function f() {
console.log(1);
}
</script>