前端 | JavaScript基础
js内容多,单独开篇。
参考网络教程为MDN Web Docs
很多人认为,与相关技术如 HTML 和 CSS 相比,学习 JavaScript 更为困难。
练习网站我用的Glitch
JavaScript
- JavaScript 第一步 3h40min
- 编写 JavaScript / JavaScript基础要件 4h
- JavaScript 对象入门 6.5h
- 异步 JavaScript 2h15min
- 客户端 Web API 4h15min
Web 表单 — 处理用户数据
- Web 表单
可访问性——让所有人都能使用 Web
- 跨浏览器测试
- 可访问性(辅助功能)
现代工具
- Git 和 GitHub
- 客户端 Web 开发工具入门
- 客户端 JavaScript 开发框架入门 (React / Ember / Vue )
服务端网页编程
- 第一步
- Django网站框架(python)
- Express网页框架(node.js / JavaScript)
JavaScript第一步
变量
一个可靠的命名约定叫做 “小写驼峰命名法”,用来将多个单词组在一起,小写整个命名的第一个字母然后大写剩下单词的首字符。我们已经在文章中使用了这种命名方法。
字符串替换
replace只会替换找到的第一个,所以有重复的部分需要替换多次。
JavaScript基础要件
条件
三元运算符
感觉不太用到,我都没什么印象……?
循环
唔这个大家都会,略【 话说我不知道为什么课后练习我用replace替换最后一位逗号不行啊?我没想通嘤嘤嘤!!
函数与方法
math.random
Math.floor(Math.random()*number) // 0到number的随机整数,左闭右开
Math.floor(Math.random()*(number+1)) // 0到number的随机整数,闭区间
Math.floor(Math.random() * (max - min)) + min // min到max的随机整数,左闭右开
Math.floor(Math.random() * (max - min + 1)) + min //min到max的随机整数,闭区间
事件
事件捕获
事件冒泡
用 stopPropagation()
打断冒泡。
JavaScript对象介绍
点表示法
括号表示法
OOP
Object-oriented programming (OOP)
类和构造函数
原型
字符串拼接
'常量'+a+'常量'
等价于 '常量连接变量${a}与常量'
彩球弹射
发现中文英文的代码居然写得不一样……
点击展开:中文版
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const width = (canvas.width = window.innerWidth);
const height = (canvas.height = window.innerHeight);
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
} // 这段我总觉得中文版的开闭区间有问题所以抄的英文版
function randomRGB() {
return `rgb(${random(0, 255)},${random(0, 255)},${random(0, 255)})`;
}
function Ball(x, y, velX, velY, color, size) {
this.x = x;
this.y = y;
this.velX = velX;
this.velY = velY;
this.color = color;
this.size = size;
}
Ball.prototype.draw = function () {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI); // 0是角度,2 * Math.PI是360°完整的圆
ctx.fill();
};
Ball.prototype.update = function() { //圆形不出框外
if ((this.x + this.size) >= width) {
this.velX = -(this.velX);
}
if ((this.x - this.size) <= 0) {
this.velX = -(this.velX);
}
if ((this.y + this.size) >= height) {
this.velY = -(this.velY);
}
if ((this.y - this.size) <= 0) {
this.velY = -(this.velY);
}
this.x += this.velX;
this.y += this.velY;
}
Ball.prototype.collisionDetect = function() { // 碰撞检测
for (let j = 0; j < balls.length; j++) {
if (this !== balls[j]) { // 不是这个圆本身
const dx = this.x - balls[j].x;
const dy = this.y - balls[j].y;
const distance = Math.sqrt(dx * dx + dy * dy); // 也就是两点之间用勾股定理求直线距离
if (distance < this.size + balls[j].size) { // 如果两个小球中心的距离小于两个小球的半径之和,判定为相撞,则改变颜色
balls[j].color = this.color = randomRGB();
}
}
}
}
let balls = [];
while (balls.length < 25) {
let size = random(10, 20);
let ball = new Ball(
// 为避免绘制错误,球至少离画布边缘球本身一倍宽度的距离
random(0 + size, width - size),
random(0 + size, height - size),
random(-7, 7),
random(-7, 7),
randomRGB(),
size
);
balls.push(ball);
}
function loop() { // 运动循环,也就是每一帧都自动更新视图。这是大多数游戏或者其他类似项目的基础。
ctx.fillStyle = 'rgba(0, 0, 0, 0.25)';
ctx.fillRect(0, 0, width, height);
for (let i = 0; i < balls.length; i++) {
balls[i].draw();
balls[i].update();
balls[i].collisionDetect();
}
requestAnimationFrame(loop); // 使用 requestAnimationFrame() 方法再运行一次函数 —— 当一个函数正在运行时传递相同的函数名,从而每隔一小段时间都会运行一次这个函数,这样我们可以得到一个平滑的动画效果。这主要是通过递归完成的 —— 也就是说函数每次运行的时候都会调用自己,从而可以一遍又一遍得运行。
}
loop();
点击展开:英文版
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const width = (canvas.width = window.innerWidth);
const height = (canvas.height = window.innerHeight);
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function randomRGB() {
return `rgb(${random(0, 255)},${random(0, 255)},${random(0, 255)})`;
}
class Ball {
constructor(x, y, velX, velY, color, size) {
this.x = x;
this.y = y;
this.velX = velX;
this.velY = velY;
this.color = color;
this.size = size;
}
draw() {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx.fill();
}
update() {
if ((this.x + this.size) >= width) {
this.velX = -(this.velX);
}
if ((this.x - this.size) <= 0) {
this.velX = -(this.velX);
}
if ((this.y + this.size) >= height) {
this.velY = -(this.velY);
}
if ((this.y - this.size) <= 0) {
this.velY = -(this.velY);
}
this.x += this.velX;
this.y += this.velY;
}
collisionDetect() {
for (const ball of balls) {
if (this !== ball) {
const dx = this.x - ball.x;
const dy = this.y - ball.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.size + ball.size) {
ball.color = this.color = randomRGB();
}
}
}
}
}
const balls = [];
while (balls.length < 25) {
const size = random(10,20);
const ball = new Ball(
// ball position always drawn at least one ball width
// away from the edge of the canvas, to avoid drawing errors
random(0 + size, width - size),
random(0 + size, height - size),
random(-7, 7),
random(-7, 7),
randomRGB(),
size
);
balls.push(ball);
}
function loop() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.25)';
ctx.fillRect(0, 0, width, height);
for (const ball of balls) {
ball.draw();
ball.update();
ball.collisionDetect();
}
requestAnimationFrame(loop);
}
loop();
点击展开:添加恶魔圈的弹球
const para = document.querySelector('p'); // 添加一个对应html中段落的常量
let count = 0; // 声明一个计数的变量
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const width = (canvas.width = window.innerWidth);
const height = (canvas.height = window.innerHeight);
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function randomRGB() {
return `rgb(${random(0, 255)},${random(0, 255)},${random(0, 255)})`;
}
class Shape {
constructor(x, y, velX, velY) { // 讲道理这个构造我还是不太明白什么时候写多少【【
this.x = x;
this.y = y;
this.velX = velX;
this.velY = velY;
}
}
class Ball extends Shape {
constructor(x, y, velX, velY, color, size) { // 比如这里为什么不用写exists啊?
super(x, y, velX, velY);
this.color = color;
this.size = size;
this.exists = true;
}
}
Ball.prototype.draw = function () {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI); // 0是角度,2 * Math.PI是360°完整的圆
ctx.fill();
};
Ball.prototype.update = function () {
//圆形不出框外
if (this.x + this.size >= width) {
this.velX = -this.velX;
}
if (this.x - this.size <= 0) {
this.velX = -this.velX;
}
if (this.y + this.size >= height) {
this.velY = -this.velY;
}
if (this.y - this.size <= 0) {
this.velY = -this.velY;
}
this.x += this.velX;
this.y += this.velY;
};
Ball.prototype.collisionDetect = function () {
for (const ball of balls) {
if (!(this === ball) && ball.exists) {
const dx = this.x - ball.x;
const dy = this.y - ball.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.size + ball.size) {
ball.color = this.color = randomRGB();
}
}
}
};
class EvilCircle extends Shape {
constructor(x, y) { // 又比如这里为什么只需要写xy啊?
super(x, y, 20,20);
this.color = "white";
this.size = 10;
}
}
EvilCircle.prototype.draw = function () {
ctx.beginPath();
ctx.lineWidth = 3;
ctx.strokeStyle = this.color;
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI); // 0是角度,2 * Math.PI是360°完整的圆
ctx.stroke();
};
EvilCircle.prototype.checkBounds = function () {
//圆形不出框外,这段倒是自己理解能写出来……就是更简略的写法也有,加减号放前面加一个等号
if (this.x + this.size >= width) {
this.x = this.x - this.size;
}
if (this.x - this.size <= 0) {
this.x = this.x + this.size;
}
if (this.y + this.size >= height) {
this.y = this.y - this.size;
}
if (this.y - this.size <= 0) {
this.y = this.y + this.size;
}
};
EvilCircle.prototype.setControls = function () {
window.onkeydown = (e) => {
switch (e.key) {
case "a":
this.x -= this.velX;
break;
case "d":
this.x += this.velX;
break;
case "w":
this.y -= this.velY;
break;
case "s":
this.y += this.velY;
break;
}
};
};
EvilCircle.prototype.collisionDetect = function () {
// 碰撞检测
for (const ball of balls) { // 这个条件语句注意
if (ball.exists) {
const dx = this.x - ball.x;
const dy = this.y - ball.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.size + ball.size) {
ball.exists = false; // 判断相撞则将该ball的exists属性改为假
count--; // 并且计数自减
para.textContent = 'Ball count: ' + count; // 计数有变动就传值
}
}
}
};
const balls = [];
while (balls.length < 25) {
const size = random(10, 20);
const ball = new Ball(
// ball position always drawn at least one ball width
// away from the edge of the canvas, to avoid drawing errors
random(0 + size, width - size),
random(0 + size, height - size),
random(-7, 7),
random(-7, 7),
randomRGB(),
size
);
balls.push(ball);
count++; // 每次循环计数自增
para.textContent = 'Ball count: ' + count; // 传值到html的段落中
}
const evilBall = new EvilCircle(random(0, width), random(0, height)); // 因为构造里只有xy所以这里也只需要两个参数
function loop() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.25)';
ctx.fillRect(0, 0, width, height);
for (const ball of balls) {
if (ball.exists) { // 若ball的exists属性为真,才绘制ball,也就解释了为什么恶魔圈碰撞检测为真,并设置相撞的ball的exists属性为假的时候,ball会“消失”
ball.draw();
ball.update();
ball.collisionDetect();
}
}
evilBall.draw();
evilBall.checkBounds();
evilBall.collisionDetect();
requestAnimationFrame(loop);
}
loop();
异步JavaScript
可以说我完全没懂吗,我自己都不知道怎么跑通了()
客户端API
这个参考答案里为什么要用异步啊我懵!!
点击展开:操作文档
const list = document.querySelector('ul');
const input = document.querySelector('input');
const button = document.querySelector('button');
function Add(){ //定义新增的要放这里面,不然只会存在一个,反复在原来的那个上修改
let cust= input.value; // 注意这里是value,我之前一直以为也是textContent(瀑布汗)
let li = document.createElement("li");
let del = document.createElement("button");
del.textContent = 'Delete';
let span= document.createElement("span");
li.appendChild(span);
li.appendChild(del);
list.appendChild(li);
span.textContent= cust;
input.value = '';
function Del(){
list.removeChild(li)
}
del.addEventListener('click', Del);
input.focus();
}
button.addEventListener('click', Add);